1.dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度
2.位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。
if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
// 注意这里不是要dp[i] 与 dp[j] + 1进行比较,而是我们要取dp[j] + 1的最大值。
3. dp[i](即最长递增子序列)起始大小至少都是1.
4. 从前向后遍历
class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
Arrays.fill(dp,1);
int res = 1;
for(int i=1; inums[j]){
dp[i] = Math.max(dp[i],dp[j]+1);
}
}
res = Math.max(res,dp[i]);
}
// 注意最长的子序列不一定是在dp[n-1]处
// 所以需要一个res去接收最大的dp值
return res;
}
}
因此就只需要与前一个比较即可
本题也可用贪心解决
class Solution {
public int findLengthOfLCIS(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
Arrays.fill(dp,1);
int res = 1;
for(int i=1; inums[i-1]){
dp[i]=dp[i-1]+1;
}
res = Math.max(res,dp[i]);
}
return res;
}
}
// 贪心
class Solution {
public int findLengthOfLCIS(int[] nums) {
int count=1;
int res = 1;
for(int i=1; inums[i-1]){
count++;
}else{
count=1;
}
res = Math.max(res,count);
}
return res;
}
}
1.dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度。
2.当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;
3.dp[i][0] 和dp[0][j]其实都没有意义,但可以初始化为0。
4.外层for循环遍历A,内层for循环遍历B。
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int m = nums1.length+1;
int n= nums2.length+1;
int res=0;
int[][] dp = new int[m][n];
for(int i=1; i
1.dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
2.递推情况如下
text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大
3.dp[i][0] = 0=dp[0][j]。
4.从前向后,从上到下来遍历
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length()+1;
int n = text2.length()+1;
int[][] dp = new int[m][n];
for(int i=1; i
直线不能相交,就是说明在字符串A中 找到一个与字符串B相同的子序列,且这个子序列不能改变相对顺序。只要相对顺序不改变,连接相同数字的直线就不会相交。
因此,本题说是求绘制的最大连线数,其实就是求两个字符串的最长公共子序列的长度!
与上一题一模一样
class Solution {
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int m = nums1.length+1;
int n = nums2.length+1;
int[][] dp = new int[m][n];
for(int i=1; i
1.dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]。
2.dp[i] = max(dp[i - 1] + nums[i], nums[i]);
3.dp[0] = nums[0]。
4.从前向后遍历。
class Solution {
public int maxSubArray(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
dp[0] = nums[0];
int res = nums[0];
for(int i=1; i
1.dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度
2.if (s[i - 1] == t[j - 1]){dp[i][j] = dp[i - 1][j - 1] + 1;}else{dp[i][j] = dp[i][j - 1];}
注意:题目要求判断s是否是t的子序列,所以只考虑删除t[j-1],而不考虑删除s[i-1].
3.dp[i][0]=0 =dp[0][j]
4.从上到下,从左到右
class Solution {
public boolean isSubsequence(String s, String t) {
int m = s.length()+1;
int n = t.length()+1;
int[][] dp = new int[m][n];
for(int i=1; i
1.dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数。
2.
3.
4.从上到下,从左到右遍历
class Solution {
public int numDistinct(String s, String t) {
int m =s.length()+1;
int n = t.length()+1;
int[][] dp = new int[m][n];
for(int i=0; i
1.dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。
2.
3.dp[i][0] = i;dp[0][j]=j
4.从上到下,从左到右遍历
class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length()+1;
int n = word2.length()+1;
int[][] dp = new int[m][n];
for(int i = 0; i
1.dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
2.
word1
替换word1[i - 1]
,使其与word2[j - 1]
相同,dp[i][j] = dp[i - 1][j - 1] + 1;3.dp[i][0] = i;dp[0][j] = j;
4.从左到右从上到下去遍历。
class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length()+1;
int n = word2.length()+1;
int[][] dp = new int[m][n];
for(int i=0; i
判断一个子字符串(字符串下标范围[i,j])是否回文,依赖于,子字符串(下标范围[i + 1, j - 1])) 是否是回文。
1.布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,
2.
3.dp[i][j]初始化为false
4.从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的
class Solution {
public int countSubstrings(String s) {
int n =s.length();
boolean [][] dp = new boolean[n][n];
int res=0;
for(int i = n-1; i>=0; i--){
for(int j=i; j
1.dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度。
2.
3.i==j时,dp[i[j]=1
4.从下到上遍历,从左向右遍历。
class Solution {
public int longestPalindromeSubseq(String s) {
int n = s.length();
int[][] dp = new int[n][n];
for(int i=n-1; i>=0; i--){
dp[i][i]=1;
for(int j=i+1; j