最长递增子序列
最长递增子序列
给你一个整数数组 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);//这里引用动态规划解法会超时
}
标签:信封,int,递增,数组,序列,最长,dp
From: https://www.cnblogs.com/ANDQE/p/16932309.html