最长递增子序列和ta的衍生题

参考 穿上衣服我就不认识你了?来聊聊最长上升子序列

主要是找出最多独立的区间

 

最长递增子序列

这是一切开始的地方

class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length, len = 0;
        int[] tails = new int[nums.length];

        for (int i = 0; i < nums.length; i++) {
            int l = 0, r = len - 1;
            while (l <= r) {
                int mid = (r - l) / 2 + l;
                if (nums[i] <= tails[mid]) { //这里要取等号,相同即替换
                    //ans = mid;
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            }
            tails[l] = nums[i];
            if (l == len) len++;
        }
        return len;
    }
}

 

动态规划 + 二分

下标为 i 表示长度为 i + 1是最长上升子序列的末尾是数字。时刻更新保证长度为i + 1的最长上升子序列的末尾的数字是最小的。

class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int[] tails = new int[nums.length];
        tails[0] = nums[0];
        int len = 1;

        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > tails[len - 1]) {
                tails[len++] = nums[i];
            }
            int l = 0, r = len - 1;
            while (l <= r) {
                int mid = (r - l) / 2 + l;
                if (nums[i] <= tails[mid]) {
                    //ans = mid;
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            }
            tails[l] = nums[i];
        }

        return len;
    }
}

 

 

无重叠区间

根据第二个元素先排序,至于原由你细品。最长上升子序的个数就是无重叠区间的个数。(贪心是最优解,这样只是提供了另一个思路)

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length == 0) return 0;
        Arrays.sort(intervals, (o1, o2) -> o1[1] - o2[1]);
        int[] dp = new int[intervals.length];
        Arrays.fill(dp, 1);
        int res = 1;
        for (int i = 1; i < intervals.length; i++) {
            for (int j = 0; j < intervals.length; j++) {
                if (intervals[i][0] >= intervals[j][1]) {
                    dp[i] = Math.max(dp[j] + 1, dp[i]);
                }
            }
            res = Math.max(dp[i], res);
        }
        return intervals.length - res;
    }
}

 

用最少数量的箭引爆气球

和上面的思路一样,有多少不重叠的区间就射多少箭。你这样想,不重叠的区间就是至少射的箭的数量,只要射得是重叠区间的交集就可以顺带把重叠区间射掉。(同样贪心跟简单,这只是另一种思路)

class Solution {
    public int findMinArrowShots(int[][] points) {
        if (points.length == 0) return 0;
        Arrays.sort(points, (o1, o2) -> (o1[1] < o2[1] ? -1 : 1));
        int res = 1;
        int[] dp = new int[points.length];
        Arrays.fill(dp, 1);
        for (int i = 0; i < points.length; i++) {
            for (int j = 0; j < i; j++) {
                if (points[i][0] > points[j][1]) {
                    dp[i] = Math.max(dp[j] + 1, dp[i]);
                }
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}

 

最长数对链

同样的配方,熟悉的味道。

class Solution {
    public int findLongestChain(int[][] pairs) {
        Arrays.sort(pairs, (o1, o2) -> o1[1] - o2[1]);
        int[] dp = new int[pairs.length];
        Arrays.fill(dp, 1);
        int res = 1;
        for (int i = 0; i < pairs.length; i++) {
            for (int j = 0; j < i; j++) {
                if (pairs[i][0] > pairs[j][1]) {
                    dp[i] = Math.max(dp[j] + 1, dp[i]);
                }
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}

 

俄罗斯套娃信封问题

二维LIS

class Solution {
    public int maxEnvelopes(int[][] envelopes) {
        if (envelopes.length == 0) return 0;
        //这里排序要注意[[1,2], [2,2],[3,2], [4,3]]要排序成[[3,2], [2,2], [1,2],[4,3]]
        Arrays.sort(envelopes, (o1, o2) -> o1[1] == o2[1] ? o2[0] - o1[0] : o1[1] - o2[1]);
        int n = envelopes.length, end = 0;
        int[] tail = new int[n];

        for (int i = 0; i < n; i++) {
            int l = 0, r = end - 1;
            while (l <= r) {
                int mid = (r - l) / 2 + l;
                if (envelopes[i][0] <= tail[mid]) {
                    //ans = mid;
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            }
            tail[l] = envelopes[i][0];
            if (l == end) end++;
        }
        return end;
    }
}

 

posted @ 2020-12-22 21:22  CPJ31415  阅读(114)  评论(0)    收藏  举报