最长回文子序列
解题思路
dp[i][j]含义:表示 s 的第 i 个字符到第 j 个字符组成的子串中,最长的回文序列长度是多少。
状态转移方程:如果 s 的第 i 个字符和第 j 个字符相同的话,那么dp[i][j] = dp[i+1][j-1] + 2;
如果 s 的第 i 个字符和第 j 个字符不同的话,那么dp[i][j] = max(dp[i+1][j],dp[i][j-1]
遍历顺序:i 从最后一个字符开始往前遍历,j 从 i + 1 开始往后遍历,这样可以保证每个子问题都已经算好了。
初始化:i == j 时dp[i][j] =1(单个字符的最长回文序列是 1)
代码实现
int longestPalindromeSubseq(char * s){
int n,i,j;
n = strlen(s);
if(n == 1){
return n;
}
int max = 1;
int dp[1001][1001]={0};
//dp[i][j]表示第i个字符到第j个字符之间的回文子序列的长度
for(i = 1;i < n+1;i ++){
dp[i][i] = 1;
}
/**dp含义、递推公式、初始化、遍历顺序
s[i] == s[j]时,那么dp[i][j] = dp[i+1][j-1] + 2;
s[i] != s[j]时,dp[i][j] = max(dp[i+1][j],dp[i][j-1]
*/
for(i = n;i >= 1;i--){
for(j = i+1;j <= n;j++){
if(s[i-1] == s[j-1]){
dp[i][j] = dp[i+1][j-1] + 2;
}else{
// dp[i][j] = fmax(dp[i+1][j],dp[i][j-1]);
if(dp[i+1][j] > dp[i][j-1]){
dp[i][j] = dp[i+1][j];
}else{
dp[i][j] = dp[i][j-1];
}
}
if(max < dp[i][j]){
max = dp[i][j];
}
}
// max = fmax(max,dp[i][j]);
}
return max;
}
打家劫舍_1
解题思路:
dp[i]含义:dp[i]表示前i步能偷的最大金额
状态转移方程:dp[i] = max(dp[i-2],dp[i-3])+ nums[i];每家必偷,再加上上一次偷的最大值
初始化:dp[0] = nums[0],dp[1] = nums[1],dp[2] = nums[2] + nums[0];
代码实现:
class Solution {
int max(int a,int b){
if(a > b)return a;
else return b;
}
public int rob(int[] nums) {
int[] dp = new int [1001];
int m = 0;
int n = nums.length;
dp[0] = nums[0];
m = max(dp[0],m);
if(n == 1){
return m;
}
dp[1] = nums[1];
m = max(dp[1],m);
if(n == 2){
return m;
}
dp[2] = nums[2] + nums[0];
m = max(dp[2],m);
if(n == 3){
return m;
}
for(int i = 3;i < n;i++){
dp[i] = max(dp[i-2],dp[i-3])+nums[i];
m = max(dp[i],m);
}
return m;
}
}
打家劫舍_2
在打家劫舍_1的基础上添加了限制条件,nums[0],nums[n-1]相邻
解题思路
改进点:当偷第一家时,dp数组在n-2就结束循环;
不偷第一家时,dp数组从dp[1]开始初始化,在dp[n-1]结束循环
找出最大的金额
边界处理:当数组只有三个时,取出最大值即可
代码实现
class Solution {
int max(int a,int b){
a = a > b ? a : b;
return a;
}
public int rob(int[] nums) {
int[] dp = new int [1001];
int n = nums.length;
int m;
if(n == 1){
return nums[0];
}
m = max(nums[0],nums[1]);
if(n == 2){
return m;
}
if(n == 3){
return max(nums[2],m);
}
dp[0] = nums[0];
dp[1] = nums[1];
dp[2] = max ,nums[1]);
m = max(dp[2],m);
for(int i = 3;i < n-1;i++){
dp [i] = max(dp[i-2],dp[i-3])+nums[i];
m = max(m,dp[i]);
}
int s;
dp[1] = nums[1];
dp[2] = nums[2];
s = max(nums[1],nums[2]);
dp[3] = max(nums[1] + nums[3],nums[2]);
s = max(dp[3],s);
for(int i=4;i<n;i++){
dp [i] = max(dp[i-2],dp[i-3])+nums[i];
s = max(s,dp[i]);
}
m = max(m,s);
return m;
}
}