class Solution{
public int climbStairs(int n){
if(n<=2) return n;
int []dp=new int[n+1];
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
}
class Solution {
public int rob(int[] nums) {
int n=nums.length;
if(n==0) return 0;
if(n==1) return nums[0];
int []dp=new int[n+1];
dp[0]=0;
dp[1]=nums[0];
for(int i=2;i<=n;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[n];
}
}
class Solution {
public int rob(int[] nums) {
if(nums.length==0) return 0;
if(nums.length==1) return nums[0];
int []nums1=new int[nums.length];
int []nums2=new int[nums.length];
nums1=Arrays.copyOfRange(nums,0,nums.length-1);//[)
nums2=Arrays.copyOfRange(nums,1,nums.length);
int n1=fun(nums1);
int n2=fun(nums2);
return Math.max(n1,n2);
}
public int fun(int []nums){
int n=nums.length;
int []dp=new int[n+1];
if(n==0) return 0;
dp[0]=0;
dp[1]=nums[0];
for(int i=2;i<=n;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[n];
}
}
class Solution {
public int minPathSum(int[][] grid) {
int m=grid.length;
if(m==0) return 0;
int n=grid[0].length;
int [][]dp=new int[m][n];
dp[0][0]=grid[0][0];
for(int i=1;i<m;i++){
dp[i][0]=dp[i-1][0]+grid[i][0];
}
for(int i=1;i<n;i++){
dp[0][i]=dp[0][i-1]+grid[0][i];
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=grid[i][j]+Math.min(dp[i-1][j],dp[i][j-1]);
}
}
return dp[m-1][n-1];
}
}
class Solution {
public int integerBreak(int n) {
int []dp=new int[n+1];
dp[2]=1;
for(int i=3;i<=n;i++){
for(int j=1;j<i;j++){
dp[i]=Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j]));
//分别表示不拆分,拆分成两个,拆分2个以上
}
}
return dp[n];
}
}
class Solution {
public int numSquares(int n) {
int []dp=new int[n+1];
for(int i=0;i<=n;i++){
dp[i]=i;
}
dp[0]=0;
dp[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j*j<=i;j++){
dp[i]=Math.min(dp[i],dp[i-j*j]+1);
}
}
return dp[n];
}
}
class Solution {
public:
int numDecodings(string s) {
if(s[0]=='0') return 0;
int n=s.length();
int dp[n+1];
dp[0]=1;
dp[1]=1;
for(int i=1;i<n;i++){
if(s[i]=='0'){
if(s[i-1]=='1'||s[i-1]=='2')
dp[i+1]=dp[i-1];
else return 0;
}
else{
if(s[i-1]=='1'||s[i-1]=='2'&&s[i]<='6'){
dp[i+1]=dp[i]+dp[i-1];
}
else{
dp[i+1]=dp[i];
}
}
}
return dp[n];
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int len=nums.size();
if(len==0) return 0;
int dp[len];
for(int i=0;i<len;i++) dp[i]=1;
int res=0;
for(int i=0;i<len;i++){
for(int j=0;j<i;j++){
if(nums[j]<nums[i]){
dp[i]=max(dp[i],dp[j]+1);
}
}
res=max(res,dp[i]);
}
return res;
}
};
//dp[i] 表示以 nums[i] 结尾的「上升子序列」的长度
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m=text1.length(),n=text2.length();
//dp[i][j] 表示text1[0~i-1]和text2[0~j-1]的最长公共子序列长度
int [][]dp=new int[m+1][n+1];
dp[0][0]=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(text1.charAt(i-1)==text2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1]+1;
}
else{
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[m][n];
}
}
//dp[i][j] 表示text1[0~i-1]和text2[0~j-1]的最长公共子序列长度
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
//可以类比于背包问题
int n=s.length();
//dp[i]表示s中以i-1结尾的字符串是否可以被拆分
boolean[]dp=new boolean[n+1];
dp[0]=true;
for(int i=1;i<=n;i++){
for(int j=0;j<i;j++){
if(dp[j]&&wordDict.contains(s.substring(j,i))){
dp[i]=true;
break;
}
}
}
return dp[n];
}
}
class Solution {
public int minDistance(String word1, String word2) {
int m=word1.length();
int n=word2.length();
int [][]dp=new int[m+1][n+1];
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1]+1;
}
else{
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return m+n-2*dp[m][n];
}
}
class Solution {
public int minDistance(String word1, String word2) {
int m=word1.length(),n=word2.length();
int [][]dp=new int[m+1][n+1];
for(int i=0;i<=m;i++){
dp[i][0]=i;
}
for(int i=0;i<=n;i++){
dp[0][i]=i;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1];
}
else{
dp[i][j]=Math.min(dp[i-1][j],Math.min(dp[i][j-1],dp[i-1][j-1]))+1;
}
}
}
return dp[m][n];
}
}
class Solution {
public boolean canPartition(int[] nums) {
int sum=0;
for(int num:nums)
sum+=num;
if(sum%2==1) return false;
sum=sum/2;
int len=nums.length;
boolean[][] dp = new boolean[len+1][sum+1];
for(int i=0;i<=len;i++) dp[i][0]=true;
for(int i=1;i<=len;i++){
for(int j=1;j<=sum;j++){
if(j<nums[i-1]){ 如果当前的背包容量比要放的数量都小,那就没法放
dp[i][j]=dp[i-1][j];
}
else{
dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
}
}
}
return dp[len][sum];
}
}