最长递增子序列
最长递增子序列
最长递增子序列
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
动态规划解法
1、确定 base case
数组中的每一个数,不和其他值比时,最初的长度都为1
2、明确 dp 函数/数组的定义
dp[i] 表示以 nums[i] 这个数结尾的最长递增子序列的长度。
public int lengthOfLIS(int[] nums) {
		int len = nums.length;
		//以num[i]结尾的构成的最长递增子序列的长度
		int dp[] = new int[len];
    //base case
		Arrays.fill(dp, 1);
		for(int i=0;i<len;i++) {
			for(int j=0;j<i;j++) {
				if(nums[i]>nums[j]) {
					dp[i]=Math.max(dp[i], dp[j]+1);
				}
			}
		}
		int res = 0;
		for(int i=0;i<len;i++) {
			res = Math.max(res, dp[i]);
		}
		return res;
    }
二分解法
未完待续.....
俄罗斯套娃信封问题
[传送门]( 354. 俄罗斯套娃信封问题 - 力扣(LeetCode) )
给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算 最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
注意:不允许旋转信封。
这道题目其实是最长递增子序列的一个变种,因为每次合法的嵌套是大的套小的,相当于在二维平面中找一个最长递增的子序列,其长度就是最多能嵌套的信封个数。
这道题的解法比较巧妙:
先对宽度 w 进行升序排序,如果遇到 w 相同的情况,则按照高度 h 降序排序;之后把所有的 h 作为一个数组,在这个数组上计算 LIS 的长度就是答案。
public int maxEnvelopes(int[][] envelopes) {
        int n =envelopes.length;
    //先对宽度w进行升序排序,如果遇到w相同的情况,则按照高度h降序排序
        Arrays.sort(envelopes, new Comparator<int[]>(){
        	public int compare(int[] a,int[] b) {
        		return a[0]==b[0]?b[1]-a[1]:a[0]-b[0];
        	}
		});
        int[] height = new int[n];
        for(int i=0;i<n;i++) {
        	height[i]=envelopes[i][1];
        }
        return lengthOfLIS(height);//这里引用动态规划解法会超时
    }

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号