Dynamic programming-subsequence problem solving template
1. One-dimensional dp array
template:
int n = array.length;
int[] dp = new int[n];
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
dp[i] = 最值(dp[i], dp[j] + ...)
}
}
The meaning of dp[i]: In the sub-array array[0...i], the length of the target subsequence ending in array[i] is dp[i]. (Similar to this)
Example: the longest increasing subsequence
Problem Description
Give you an integer array nums and find the length of the longest strictly increasing subsequence.
A subsequence is a sequence derived from an array, deleting (or not deleting) elements in the array without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].
Problem-solving ideas
Define dp[i] to represent the length of the longest increasing subsequence ending with nums[i] . If dp[i] is required, then max(dp[1],dp[2],…,dp [i-1]), assuming max(dp[1],dp[2],…,dp[i-1]) = dp[j], then if nums[i]> nums[j], then dp[ i] = dp[j] + 1, otherwise dp[i] remains unchanged.
Code
class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;//求出数组元素个数
if(n == 0) //若数组为空,返回0
return 0;
int dp[] = new int[n];//dp[i]表示以nums[i]结尾的最大递增子序列长度
int result = -1;
for(int i=0;i<n;i++){
dp[i] = 1; //初始都为1
for(int j=0;j<i;j++){
//dp[0]开始
if(nums[i]>nums[j])//若nums[i]>nums[j]则dp[i]可以为dp[j]+1,否则对dp[i]不做处理
dp[i] = Math.max(dp[i],dp[j]+1);
}
result = Math.max(dp[i],result);
}
return result;
}
}
Time complexity: O(n^2)
Space complexity: O(n)
2. Two-dimensional dp array
template:
int n = arr.length;
int[][] dp = new dp[n][n];
for (int i = 0; i < n; i++) {
for (int j = 1; j < n; j++) {
if (arr[i] == arr[j])
dp[i][j] = dp[i][j] + ...
else
dp[i][j] = 最值(...)
}
}
The meaning of dp[i][j]:
- When two strings/arrays are involved: In the sub-array arr1[0...i] and the sub-array arr2[0...j], the length of the sub-sequence we require is dp[i][j]. Example: edit distance, longest common subsequence...
- When only one string/array is involved: In the sub-array array[i...j], the length of the sub-sequence we require is dp[i][j]. Example: the longest palindrome subsequence...
Example: the longest palindrome subsequence
Problem Description
Given a string s, find the longest palindrome subsequence, and return the length of the sequence. It can be assumed that the maximum length of s is 1000.
Problem-solving ideas
Define dp[i][j] as the length of the longest palindrome subsequence in the substring s[i,...,j], assuming that dp[i+1][j-1] is known at this time, then if s[i ]==s[j], then dp[i][j] = dp[i+1][j-1] + 2; otherwise it is equal to max(dp[i+1][j],dp[i][ j-1]).
Code
class Solution {
public int longestPalindromeSubseq(String s) {
int n = s.length();
if(n == 0) return 0;
int dp[][] = new int[n][n];
for(int i=n-1;i>=0;i--){
dp[i][i] = 1;// i==j时回文串长度为1
for(int j=i+1;j<n;j++){
if(s.charAt(i) == s.charAt(j))
dp[i][j] = dp[i+1][j-1]+2;
else
dp[i][j] = Math.max(dp[i+1][j],dp[i][j-1]);
}
}
return dp[0][n-1];
}
}