动态规划 --- 序列上的动规
674.最长连续递增子序列
动态规划:
- 要求连续, 所以只需要和前一个值进行比较就行
- 初始化: 每个元素都是最少长度为
1的最长递增子序列-所以全部初始化成1 - 不以终点为最优解的动规需要在过程中不断记录最优解
代码:
class Solution {
// 注意: 连续和不连续的区别:
// 1. 连续的话只需要和前一个值进行比较
// 2. 不连续的话需要从其之前的所有位置都进行比较
// 3. 找出最长的, 不一定是以终点为结尾的最优解, 需要在动规过程中记录最值
public int findLengthOfLCIS(int[] nums) {
int ans = 1;
int n = nums.length;
int[] dp = new int[n];
Arrays.fill(dp, 1);
for(int i=1; i < n; i++){
if(nums[i] > nums[i-1]){
dp[i] = dp[i-1] + 1;
}
ans = Math.max(ans, dp[i]);
}
return ans;
}
}
300.最长递增子序列
动态规划:
- 本题不要求连续, 所以当前值需要和之前的每一个值进行比较
- 需要在比较过程中不断记录最优解
代码:
class Solution {
// 注意子序列和子数组的区别: 子数组要求连续, 子序列不要求连续
public int lengthOfLIS(int[] nums) {
int ans = 1;
int[] dp = new int[nums.length];
Arrays.fill(dp, 1);
for(int i=1; i<nums.length; i++){
for(int j=0; j < i; j++){
if(nums[j] < nums[i]){
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
ans = Math.max(ans, dp[i]);
}
return ans;
}
}
718.最长重复子数组
动态规划:
- 一般两个数组或者两个序列求公共最长: 二维
dp - 两个for循环遍历: 处理元素相等和不相等的情况
dp[m][n]数组含义:以nums1的i结尾的, 以nums2的j结尾的最长重复子数组长度- 为了不必要的初始化, 可以初始动规数组长度为
dp[m+1][n+1] - 进行比较时, 为了防止原数组超出长度, 比较
nums1[i-1]和nums2[j-1]即可
代码:
class Solution {
// 一般两个数组或者两个字符串进行动规---二维dp
// 注意子数组要求连续
// 两个for循环遍历两个数组: 判断两个数字相等的情况和两个数字不相等的情况
public int findLength(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
// dp数组含义: 以nums1的i结尾的, 以nums2的j结尾的最长重复子数组长度
int[][] dp = new int[m + 1][n + 1];
int ans = 0;
for(int i=1; i <= m; i++){
for(int j=1; j<= n; j++){
if(nums1[i-1] == nums2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else dp[i][j] = 0;
ans = Math.max(ans, dp[i][j]);
}
}
return ans;
}
}