序列DP
| 题目 | 难度 | |
|---|---|---|
| 354. 俄罗斯套娃信封问题 | 困难 | |
| 368. 最大整除子集 | 中等 | |
| 446. 等差数列划分 II - 子序列 | 困难 | |
| 740. 删除并获得点数 | 中等 | |
| 740. 删除并获得点数 | 中等 | |
| 1035. 不相交的线 | 困难 | |
| 1143. 最长公共子序列 | 中等 | |
| 1473. 粉刷房子 III | 困难 | |
| 1473. 粉刷房子 III | 困难 |
最长公共子序列问题(LCS)
序列dp,一般是求递增子序列。暴力解法是O(m*n),是所求子序列的长度。从i=0开始遍历目标数组target,从j-i的位置检查是否递增,用一个数组保存二米个位置的递增情况,检查结果dp[i] = Math.max(dp[i],dp[i-1]+1),求得当前位置的最大递增子序列的长度。
最长上升子序列问题(LIS)进行求解
如果target数组中的元素各不相同,可以通过二分查找的方法。dp长度为目标数组长度+1,并设置为最大值,每次从1-i+1位置的数组中,二分查找,找到以当前值为最大值的inndex,并对dp[index]进行更新,ans = Math.max(ans,index).
//leetcode_334
public static void main(String[] args) {
int[] nums = {2,1,5,0,4,6};
System.out.println(increasingTriplet(nums));
}
public static boolean increasingTriplet(int[] nums) {
if(nums.length <3) return false;
int n = nums.length;
int ans = 0;
int[] f = new int[n+1];
Arrays.fill(f,Integer.MAX_VALUE);
for (int i = 0; i < n; i++) {
int t = nums[i];
//在l--r维护一个以当前数字结尾的递增子序列
int l = 1, r = i + 1;
while (l < r) {
//二分查找,更换将当前数字放入l-r中的数组中
int mid = l + r >> 1;
if (f[mid] >= t) r = mid;
else l = mid + 1;
}
//找到该位置进行替换
f[r] = t;
ans = Math.max(ans, r);
}
return ans >= 3;
}