子序列是序列的一部分,元素可以不连续。
子串是字符串的一部分,必须连续。
求子序列的和、连续递增子序列都是经典的一维动态规划问题。
这一类题目都有差不多的思路,我们看案例。
案例1:有一个整数数组 nums
,请你找出一个具有最大和的连续子数组,返回其最大和。子数组是数组中的一个连续部分。
我们假设数组nums长度为n,定义dp[i]为以nums[i]结尾的连续子数组的和,接下来需要考虑dp[i]和dp[i-1]是什么关系?
显而易见,如果dp[i-1]是大于0的,那么
dp[i]=dp[i-1]+nums[i]
如果dp[i-1]<=0,那么nums[i]加上一个负数一定比自己还小,索性不如不加
dp[i]=nums[i]
这样我们就得到了动态转移方程,接下来上代码
public int maxSubArray(int[] nums) { if (nums == null || nums.length == 0) { return 0; } //定义dp[i]为以nums[i]结尾的子数组的和 int[] dp = new int[nums.length]; dp[0] = nums[0]; //最大值未必以最后一个元素结尾,所有需要遍历所有dp元素 int maxAns = nums[0]; for (int i = 1; i < nums.length; i++) { if (dp[i - 1] > 0) { dp[i] = dp[i - 1] + nums[i]; } else { dp[i] = nums[i]; } if (dp[i] > maxAns) { maxAns = dp[i]; } } return maxAns; }
案例2:有一个整数数组 nums ,找到其中最长严格递增子序列的长度。
大家记住,子序列可以是不连续的。
我们假设dp[i]是以nums[i]结尾的递增序列,那么dp[i]和dp[i-1]是什么关系呢?
这个需要分两种情况,如果nums[i]>nums[i-1],那么dp[i]就可以接在dp[i-1]后面,
dp[i]=dp[i-1]+1
因为子序列可以不连续,我们接不上nums[i-1]可以考虑下前面的元素能不能接上。
如果nums[i]>nums[i-2],dp[i]就能接在dp[i-2]后面,dp[i]=dp[i-2]+1
综上所述,dp[i]等于所有比nums[i]的nums[j]对应的dp[j]+1
动态转移方程:
dp[i]=max{dp[j]+1 :nums[i]>nums[j],0<j<i}
class Solution { public int longestCommonSubsequence(String text1, String text2) { int m = text1.length(); int n = text2.length(); int[][] dp = new int[m+1][n+1]; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (text1.charAt(i-1) == text2.charAt(j-1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]); } } } return dp[m ][n ]; } }
标签:nums,int,length,数组,序列,动态,规划,dp From: https://www.cnblogs.com/wangbin2188/p/16847376.html