力扣labuladong一刷day60天动态规划

力扣labuladong一刷day60天动态规划

文章目录

      • 力扣labuladong一刷day60天动态规划
      • 一、300. 最长递增子序列
      • 二、354. 俄罗斯套娃信封问题

一、300. 最长递增子序列

题目链接:https://leetcode.cn/problems/longest-increasing-subsequence/description/
思路:定义dp数组,dp[i]表示在[0,i]区间以nums[i]为结尾时的最长子序列的长度。子序列的起始位置可以是任意一个位置,故dp数组全部初始化为1。求dp[i]需要考虑区间[0,i-1]内的每一个元素是否加入,进行考虑还有一个先决条件,即nums[j]

class Solution {
     public int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        Arrays.fill(dp, 1);
        int max = 1;
        for (int i = 1; i < nums.length; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    dp[i] = Math.max(dp[i], dp[j]+1);
                }
            }
            max = Math.max(dp[i], max);
        }
        return max;
    }
}

二、354. 俄罗斯套娃信封问题

题目链接:https://leetcode.cn/problems/russian-doll-envelopes/description/
思路:和上题类似,不过需要先排序一下,降二维为一维,[[5,4],[6,4],[6,7],[2,3]],a[i][0]先升序,若相等a[i][1]降序,之后就降低为一维了和上一题的处理步骤一样了,但是动态规划的时间复杂度是n2,超时了。

class Solution {
     public int maxEnvelopes(int[][] envelopes) {
        Arrays.sort(envelopes, (e1, e2) -> {
            return e1[0] == e2[0] ? e2[1] - e1[1] : e1[0] - e2[0];
        });

        int[] dp = new int[envelopes.length];
        Arrays.fill(dp, 1);
        int max = 1;
        for (int i = 1; i < envelopes.length; i++) {
            for (int j = 0; j < i; j++) {
                if (envelopes[j][1] < envelopes[i][1]) {
                    dp[i] = Math.max(dp[i], dp[j]+1);
                }
            }
            max = Math.max(dp[i], max);
        }
        return max;
    }
}

采用二分查找的方法可以把时间复杂度降低到nlogn。

class Solution {
     public int maxEnvelopes(int[][] envelopes) {
        Arrays.sort(envelopes, (e1, e2)->{
            return e1[0] == e2[0] ? e2[1]-e1[1] : e1[0]-e2[0];
        });
        List<Integer> list = new ArrayList<>();
        list.add(envelopes[0][1]);
        for (int i = 1; i < envelopes.length; i++) {
            int temp = envelopes[i][1];
            if (temp > list.get(list.size()-1)) {
                list.add(temp);
            }else {
                list.set(bs(list, temp), temp);
            }
        }
        return list.size();
    }
    int bs(List<Integer> nums, int target) {
        int left = 0, right = nums.size()-1;
        while (left < right) {
            int mid = left + (right-left)/2;
            if (nums.get(mid) < target) {
                left = mid + 1;
            }else {
                right = mid;
            }
        }
        return left;
    }
}

你可能感兴趣的:(力扣算法题,leetcode,动态规划,算法)