目录
基本概念
动态规划法利用问题的最优性原理,以自底向上的方式从子问题的最优解逐步构造出整个问题的最优解。
动态规划法设计算法一般分成三个阶段:
- 分段:将原问题分解为若干个相互重叠的子问题;
- 分析:分析问题是否满足最优性原理,找出动态规划函数的递推式;
- 求解:利用递推式自底向上计算,实现动态规划过程。
力扣题
5. 最长回文子串
给定一个字符串
s
,找到s
中最长的回文子串。你可以假设s
的最大长度为 1000。示例 1:
输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd" 输出: "bb"
本题定义一个二维数组d[][],d[i][j]的值的含义代表字符串中的第i个字母到第j个字母组成的子串是否为回文。
该方法的好处是可以不用重复判断,难点在于要思考状态转移方程。
class Solution {
public String longestPalindrome(String s) {
int length=s.length();
if(length<2) return s;
int max=1,begin=0;
boolean bool[][]=new boolean[length][length];//动态规划事实是在填这张二维表
char[] charArray=s.toCharArray();//将s存进字符数组
for(int i=0;i<length;i++)//初始化表,因为对角线上的数代表的子串只有一个,一定是回文
bool[i][i]=true;
for(int j=1;j<length;j++)
for(int i=0;i<j;i++)
{
if(charArray[i]!=charArray[j])
bool[i][j]=false;
else{
if(j-i<3)//如果j-i<3说明该串字符数小,不需要再判断
bool[i][j]=true;
else
bool[i][j]=bool[i+1][j-1];//相当于字符串两头各删了一个字符,是否为回文的状态相同
}
if(bool[i][j]&&j-i+1>max)
{
max=j-i+1;
begin=i;
}
}
return s.substring(begin,begin+max);
}
}
70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
这个问题可以被分解为一些包含最优子结构的子问题,即它的最优解可以从其子问题的最优解来有效地构建
因为第i阶台阶可以由第i-1阶爬一阶,还可以由第i-2阶爬两阶得到。
class Solution {
public int climbStairs(int n) {
if(n==1){
return 1;
}
if(n==2){
return 2;
}
int[] dp=new int[n];
dp[0]=1;
dp[1]=2;
for(int i=2;i<n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n-1];
}
}
322. 零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:输入: coins = [2], amount = 3
输出: -1
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp=new int[amount+1];
Arrays.fill(dp,amount+1);
dp[0]=0;
for(int i=1;i<=amount;i++){
for(int j=0;j<coins.length;j++){
if(coins[j]<=i){
dp[i]=Math.min(dp[i],dp[i-coins[j]]+1);//递推式,由下向上
}
}
}
return dp[amount]==amount+1?-1:dp[amount];
}
}