首页 > 其他分享 >LIS 最长递增子序列 三种求解方式

LIS 最长递增子序列 三种求解方式

时间:2022-11-10 20:22:25浏览次数:42  
标签:val idx 求解 int 递增 ans LIS o2 dp

1 dp

2 二分

3 index tree

 

题目描述
给出一个列表如[[6,7,],[5,4],[3,2]],表示木块的长和宽,当木块的长和宽不大于另个木块的长和宽时,就可以放在上面,此外数组还可以左右翻转。求最多能搭多少层。

输入描述
一个二维数组,里面是每个积木的长和宽,可以左右翻转。

输出描述
最多能搭多少层。

样例
输入
[[5,4],[6,3],[6,7],[6,6],[4,6]]
1
输出
4
————————————————

package com.company;

import java.io.FileInputStream;
import java.util.*;

// 叠积木
public class Solution32 {
    static int[] lisTree;
    public static void main(String[] args) throws Exception {
        System.setIn(new FileInputStream("D:/data.txt"));
        Scanner sc = new Scanner(System.in);
        String[] split = sc.nextLine().split("],");
        ArrayList<int[]> arr = new ArrayList<>();
        for (int i = 0; i < split.length; i++) {
            String s = split[i].replaceAll("\\[", "").replaceAll("]", "");
            String[] strings = s.split(",");
            int a = Integer.valueOf(strings[0]);
            int b = Integer.valueOf(strings[1]);
            arr.add(new int[]{a>b ? a : b, a <= b ? a : b}); // 长的按照长进行组合
        }

        Collections.sort(arr, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if(o1[0] == o2[0]) return o1[1] - o2[1];
                return o1[0] - o2[0];
            }
        });

        int len = arr.size();
        // method1 dp
        int ans = 0;
        int[] dp = new int[len];

        Arrays.fill(dp, 1);
        for (int i = 0; i < len; i++) {
            int[] cur = arr.get(i);
            for (int j = 0; j < i; j++) {
                int[] pre = arr.get(j);
                if(cur[1] >= pre[1]) {
                    dp[i] = dp[j] + 1;
                }
            }

            if(dp[i] > ans) ans = dp[i];
        }
        System.out.println(ans);

        ans = 0;
        // method2 二分法
        dp[ans++] = arr.get(0)[1];
        for (int i = 1; i < len; i++) {
            int[] cur = arr.get(i);
            if(cur[1] >= dp[ans - 1]) {
                dp[ans++] = cur[1];
            } else {
                int left = 0, right = ans;

                while(left < right) {
                    int mid = left + (right - left) / 2;

                    int[] c = arr.get(mid);

                    if(cur[i] > c[1]) {
                        left = mid + 1;
                    }

                    if(cur[1] <= c[1]) {
                        right = mid;
                    }
                }

                dp[left] = cur[1];
            }
        }

        System.out.println(ans);
        // method3 indexTree
        // 1. 计算构造树需要的的len
        int size = 1;
        while (size < len) {
            size += size;
        }
        lisTree = new int[size * 2];

        // 2. 构造进行操作计算的数据
        Node[] data = new Node[len];
        for (int i = 0; i < len; i++) {
            int[] ints = arr.get(i);
            data[i] = new Node(i, ints[1]);
        }

        // 3. 对索引树进行排序
        Arrays.sort(data, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                if(o1.val == o2.val) {
                    return o1.idx - o2.idx; // 求不递增 索引小在前
                }
                return o1.val - o2.val;
            }
        });

        // 4. 定义 query 和 update 方法

        // 5. 查询和更新索引树
        for (int i = 0; i < len; i++) {
            int val = query(size, data[i].idx + size);
            update(data[i].idx + size, val + 1);
        }

        System.out.println(query(size, size * 2 - 1));
    }

    private static int query(int s, int e) {
        int ret = 0;

        while (s <= e) {
            if(s % 2 == 1) ret = Math.max(ret, lisTree[s]);
            if(e % 2 == 0) ret = Math.max(ret, lisTree[e]);
            s = (s+1) >> 1;
            e = (e-1) >> 1;
        }

        return ret;
    }

    private static void update(int idx, int val) {
        while (idx > 0) {
            lisTree[idx] = val;
            idx >>= 1;
        }
    }

    static class Node {
        int idx;
        int val;

        public Node(int idx, int val) {
            this.idx = idx;
            this.val = val;
        }
    }
}

  

标签:val,idx,求解,int,递增,ans,LIS,o2,dp
From: https://www.cnblogs.com/ives-xu/p/16878632.html

相关文章