//动态规划:转移方程:dp[n] = dp[n-1] + dp[n-2] 初始化:dp[0] =1 , dp[1] =1;
class Solution {
public int climbStairs(int n) {
int[] dp = new int[n+1];
dp[0]=dp[1]=1;
for(int i=2 ; i<n+1; i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
}
//动态规划:典型思想,我们一定要注意动态规划的思想,就是先看成一个一个的小问题,然后每一个小问题都找到一个最优解,然后再此基础上得出最后解
//首先这个基础解,我们要求的是n的由完全平方得到的最小值,此时我们应该找0~n-1的最优解,然后在此基础上得到n的最优解
class Solution {
public int numSquares(int n) {
//首先我们用数组表示,数组最后的下标为n,里面相应出的值为结果,也就是最后要返回res[n];
int[] res = new int[n+1];
//根据动态规划思想,我们找出每一个小问题的最优解,也就是0~n-1,0的时候自然res[0]=0
for(int i=1 ; i<=n ; i++){
//每个小问题的“最差的解”也就是由1*1组成,也就是
res[i] = i ;
//然后我们找当前值的“最优解”,(一定要注意动态规划思想,此时j是要找到的临界值,其实也就是小于i的最大的方法值,然后i-j*j后得到的数值是我们之前小问题已经求得的最优解)
for(int j=1 ; i-j*j>=0; j++){
res[i] = Math.min(res[i],res[i-j*j]+1);
}
}
return res[n];
}
}
//思路:(动态规划)首先我们考虑的是动态规划,其实一个回文子串,那么去了它的首尾段也是回文子串,所以我们分成一个一个小问题,
//比如说“一个字母”一定是回文子串,如果他的首尾是相同的字母那么他也是一个回文子串,以此类推,因此我们去找动态规划的状态转移方程以及边界条件
//状态转移方程:S(i,j) = S(i+1.j-1) && Si==Sj ,并且
//边界条件:长度为1时,一定是一个回文子串,2时,两个值相等一定是一个回文子串
class Solution {
public String longestPalindrome(String s) {
//记录回文子串得长度,以及开始位置
int maxLen = 1;
int begin = 0;
//首先得到字符串的长度
int len = s.length();
//当长度小于为0,1时那一定是回文子串
if(len<2){
return s;
}
//创造dp[],一般动态规划我们可以用一个二维数组表示
boolean[][] dp = new boolean[len][len];
//因为1个长度一定是回文子串,则[i][i]=true
for(int i=0 ; i<len ; i++){
dp[i][i] = true;
}
//我们将字符串变为数组,方便根据下标找值
char[] charArray = s.toCharArray();
//我们开始递推,因为我们找的回文子串长度是大于1的,所以我们从2开始遍历,最长是字符串的长度
for(int L=2 ; L <= len ; L++){
//我们要枚举子串长度
for(int i=0 ; i<len ; i++){
//当我们从第i个字母开始,并且长度为L,则尾字母应该是j,且满足j-i+1 = L.得
int j = L + i - 1;
//但是如果此时j超过了字符串长度,就退出当前循环
if(j>=len){
break;
}
//解下来我们就看长度为L得有没有回文子串(看的其实就是首尾)
if(charArray[i]!=charArray[j]){
dp[i][j] =false;
}else{
//说明相等,当长度为1时,一定是回文子串,前面已经dp[i][i]=true来表示,
//当为2时,不能通过 dp[i][j] = dp[i+1][j-1]来判断,只能直接设定
if(j-i<2){
dp[i][j] = true;
}else{
dp[i][j] = dp[i+1][j-1];
}
}
//此时我们找出了i,j,判断dp[i][j]是否为true,并且为长度只要大于1我们就记录
if(dp[i][j]&&j-i+1>maxLen){
maxLen = L;
begin =i;
}
}
}
return s.substring(begin,begin+maxLen);
}
}