【专题】动态规划

【专题】动态规划

刷题顺序来自https://leetcode-cn.com/circle/article/48kq9d/

更新记录

1.29

509、70、338、45

1.30

55、198、213、650、91

数组中的动态规划

509. 斐波那契数

image-20210129191612042

/*
*	dp[i]=dp[i-1]+dp[i-2];
*	dp[0]=0;
*	dp[1]=1;
*/
class Solution {
public:
    int fib(int n) {
        int even=0,odd=1;
        for(int i=2;i<=n;i++){
            if(i%2==0){
                even=even+odd;
            }
            else{
                odd=even+odd;
            }
        }
        return n%2==0 ? even:odd;
    }
};

image-20210129191637711

70. 爬楼梯

image-20210129191800755

/*
*dp[i]记录爬到第i节楼梯的方法的数目
*最后一次爬楼梯,只有两种情况:
*要么在倒数第1个台阶,要么在倒数第2个台阶。所以:
*dp[i]=dp[i-1]+dp[i-2]
*dp[2]=2;
*dp[1]=1;
*/
class Solution {
public:
    int climbStairs(int n) {
		int odd=1,even=2;
        for(int i=3;i<=n;i++){
            if(i%2==0){
                even=even+odd;
            }
            else{
                odd=even+odd;
            }            
        }
        return n%2==0 ? even:odd;
    }
};

image-20210129193022029

338. 比特位计数

image-20210129193118457

/*
*even=(even/2)<<1
*odd=(odd/2)<<1+1
*所以偶数和它的二分之一的二进制中的1个数相等,如8和4和2都只有1个1
*奇数就不解释了
*/
class Solution {
public:
    vector<int> countBits(int num) {
		vector<int> count_bits;
        count_bits.push_back(0);
        for(int i=1;i<=num;i++){
            i%2==0 ? count_bits.push_back(count_bits[i/2]): count_bits.push_back(count_bits[i/2]+1);
        }
        return count_bits;
    }
};

image-20210129195204001

45. 跳跃游戏 II(***超时,等到学完贪心重新做)

image-20210129195336791

//思路:left 和 right 之间 是同一个最小step能到达的范围,
//step+1则为范围right+1,max{dp[i]+i},left<=i<=right
class Solution {
public:
    int jump(vector<int>& nums) {
        if(nums.size()==1)
            return 0;
        int left=1;
        int right=nums[0];
        int step=1;
        int max=nums[0];
        while(right<nums.size()-1){
            step++;
            for(int i=left;i<=right;i++){
                if(max<i+nums[i]){
                    max=i+nums[i];
                }
            }
            right=max;
        }
        return step;
    }
};

55. 跳跃游戏

image-20210129202427707

class Solution {
public:
    bool canJump(vector<int>& nums) {
		if(nums.size()==1)
            return true;
        int left=1;
        int right=nums[0];
        int max=nums[0];
        while(right<nums.size()-1){
            for(int i=left;i<=right;i++){
                if(max<i+nums[i]){
                    max=i+nums[i];
                }
            }
            if(max==right)
                return false;
            right=max;
        }
        return true;
    }
};

image-20210130163227162

性能很差

198. 打家劫舍

image-20210130163301258

//用两个数组,A[i]表示偷当前家的总金额,B[i]表示不偷
//那么A[i]=B[i-1]+nums[i],B[i]=max{A[i-1],B[i-1]}
class Solution {
public:
    int rob(vector<int>& nums) {
        int length=nums.size();
        if(length==0)
            return 0;
        int *A=new int[length];
        int *B=new int[length];
        A[0]=nums[0];
        B[0]=0;
        for(int i=1;i<length;i++){
            A[i]=B[i-1]+nums[i];
            B[i]=(A[i-1]>B[i-1]?A[i-1]:B[i-1]);
        }
        return A[length-1]>B[length-1]?A[length-1]:B[length-1];
    }
};

image-20210130163323921

213. 打家劫舍 II

image-20210130163343395

//两种情况:不偷0家:正常和上面一样计算1到n-1的方程的值;偷0家,那么1不偷,n-1不能偷,计算2到n-2的方程
class Solution {
public:
    int rob(vector<int>& nums) {
		int length=nums.size();
        if(length==0)
            return 0;
        if(length==1)
            return nums[0];
        if(length==2)
            return nums[0]>nums[1]? nums[0]:nums[1];
        if(length==3)
            return nums[0]>nums[1]?(nums[0]>nums[2]?nums[0]:nums[2]):(nums[1]>nums[2]?nums[1]:nums[2]);
        int *A=new int[length];
        int *B=new int[length];
        //不偷0
        A[1]=nums[1];
        B[1]=0;
        for(int i=2;i<length;i++){
            A[i]=B[i-1]+nums[i];
            B[i]=(A[i-1]>B[i-1]?A[i-1]:B[i-1]);            
        }
        int max1=A[length-1]>B[length-1]?A[length-1]:B[length-1];
        //偷0
        A[2]=nums[2];
        B[2]=0;
        for(int i=3;i<length-1;i++){
            A[i]=B[i-1]+nums[i];
            B[i]=(A[i-1]>B[i-1]?A[i-1]:B[i-1]);            
        }
        int max2=A[length-2]>B[length-2]?(A[length-2]+nums[0]):(B[length-2]+nums[0]);
        return max1>max2?max1:max2;
    }
};

image-20210130163431021

650. 只有两个键的键盘

image-20210130163542455

//dp[1]=0
//dp[i]=min{dp[j]+1(复制的一次)+(i/j-1)(粘贴的次数)|j为i的所有约数}
//
class Solution {
public:
    int minSteps(int n) {
		int *dp=new int[n+1];
        dp[1]=0;
        for(int i=2;i<=n;i++){
            dp[i]=i;
        }
        for(int i=2;i<=n/2;i++){
            int mul=2;
            int j=i*mul;
            while(j<=n){
                int temp=dp[i]+mul;
                if(temp<dp[j]){
                    dp[j]=temp;
                }
                mul++;
                j+=i;
            }
        }
        return dp[n];
    }
};

image-20210130174215084

91. 解码方法

image-20210130195854911

image-20210130205339861

class Solution {
public:
    int numDecodings(string s) {
		if(s[0]=='0')
            return 0;
        int size=s.size();
        int *dp=new int[size];
        dp[0]=1;
        if(size==1){
            return 1;
        }
                //判断是否合法
        for(int i=1;i<size;i++){
            if(s[i]=='0'){
                if(s[i-1]!='1'&&s[i-1]!='2')
                    return 0;
            }
        }  
        dp[1]=(s[1]=='0')?1:(canCombined(s,1) ? 2:1);
        if(size==2){
            return dp[1];
        }
        
        if(s[1]=='0'||s[2]=='0'){
            dp[2]=1;
        }
        else{
            dp[2]=canCombined(s,2)?(canCombined(s,1)?3:2):(canCombined(s,1)?2:1);
        }
        if(size==3){
            return dp[2];
        }
     
        for(int i=3;i<size;i++){
            switch (whichCase(s,i)){
                case 0:
                    dp[i]=dp[i-2];
                    break;
                case 1:
                    dp[i]=dp[i-3]+2*dp[i-2];
                    break;
                case 2:
                    dp[i]=2*dp[i-2];
                    break;
                case 3:
                    dp[i]=dp[i-1];
                    break;
            }
        }
        return dp[size-1];
    }
    bool canCombined(string s,int i){
        //i>=1
        if(s[i-1]=='0'||s[i-1]>'2')
            return false;
        if(s[i-1]=='2'&&s[i]>'6')
            return false;
        return true;
    }
    int whichCase(string s,int i){
        if(s[i]=='0') return 0;
        return canCombined(s,i)?(canCombined(s,i-1)?1:2):3;
    }
};

image-20210130222754342

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值