dp算法训练(未完)


第N个斐波那契数列

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int tribonacci(int n) {
        int a[4]={0,1,1,2};
 
        if(n<4) return a[n];
        int k=n-3;
        for(int i=0; i<k;i++)
        {
            int tmp=a[3];
            a[3]=a[1]+a[2]+a[3];//不是【0】开始,而是【1】开始
 
            a[0]=a[1];
            a[1]=a[2];
            a[2]=tmp;
        }
        return a[3];
    }
};

三步问题

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int waysToStep(int n) {
 
        vector<int> dp(n+1,1);
        if(n==1) return 1;
 
        dp[1]=1;
        dp[2]=2;
 
        for(int i=3; i<n+1; i++)
        {
            dp[i]= ((dp[i-1]+dp[i-2])%1000000007+dp[i-3])%1000000007;//数据超出整形题目的要求处理
        }
 
        return dp[n];
    }
};

最小花费爬楼梯

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n=cost.size();
        vector<int> dp(n,0);
        dp[0]=cost[0],dp[1]=cost[1];

        for(int i=2; i<n; i++)
        {
            dp[i]=min(dp[i-1],dp[i-2])+cost[i];
        }

        return min(dp[n-1],dp[n-2]);
    }
};



解码的方法

 

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int numDecodings(string s) {
        int n=s.size();
        //if(n==1) return 1;不一定能解码成功
        vector<int> dp(n+1);
        //dp[0]=1,dp[1]=1;//s[0]不一定能解码成功
        dp[0]=1;
        for(int i=1; i<n+1; i++)
        {
            //if(s[i-2]!=0&&((s[i-2]*10+s[i-1])<='Z'))//填表的映射,画图理解。
            if(s[i-1]!='0')//单独解码,注意填的是字符‘0’
            dp[i]+=dp[i-1];
            if(i>1&&s[i-2]!='0')
            {
                int a=s[i-2]-'0',b=s[i-1]-'0';
                if(a*10+b<=26)
                    dp[i]+=dp[i-2];
            }
        }
        for(auto e:dp)
        {
            cout<<e<<endl;
        }
        return dp[n];
    }
};

打家劫舍

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int rob(vector<int>& nums) {
        int n=nums.size();
        vector<int> f(n+1);//偷的dp表
        vector<int> g(n+1);//不偷的dp表,f[0],g[0]都是初始化为0
        for(int i=1; i<n+1; i++)
        {
            f[i]=g[i-1]+nums[i-1];
            g[i]=max(g[i-1],f[i-1]);
        }

        return max(f[n],g[n]);
    }
};

打家劫舍||

 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int n=0;
    int rob(vector<int>& nums) {
        //偷了第一个就不能偷最后一个,偷的区间变成了[0,n-2]
        //偷了最后一个就不能偷第一个,..............[1,n-1]
        n=nums.size();
        if(n==1) return nums[0];
        return max(r(nums,0,n-2),r(nums,1,n-1));
    }

    int r(vector<int>& nums, int left, int right)
    {
        vector<int> f(n);//偷的dp表
        vector<int> g(n);//不偷的dp表,f[0],g[0]都是初始化为0
        
        for(int i=1; i<n; i++)
        {
            f[i]=g[i-1]+nums[left];
            left++;
            g[i]=max(f[i-1],g[i-1]);
        }

        return max(f[n-1],g[n-1]);
    }
};

利用左右区间固定的方法,封装性更好 

class Solution {
public:
    int n=0;
    int rob(vector<int>& nums) {
        //偷了第一个就不能偷最后一个,偷的区间变成了[0,n-2]
        //偷了最后一个就不能偷第一个,..............[1,n-1]
        n=nums.size();
        if(n==1) return nums[0];
        return max(r(nums,0,n-2),r(nums,1,n-1));
    }

    int r(vector<int>& nums, int left, int right)
    {
        vector<int> f(n+1);//偷的dp表
        vector<int> g(n+1);//不偷的dp表,f[0],g[0]都是初始化为0
        
        // for(int i=1; i<n; i++)
        // {
        //     f[i]=g[i-1]+nums[left];
        //     left++;
        //     g[i]=max(f[i-1],g[i-1]);
        // }
        for(int i=left+1; i<=right+1; i++)
        {
            f[i]=g[i-1]+nums[i-1];
            g[i]=max(f[i-1],g[i-1]);
        }
        return max(f[right+1],g[right+1]);
        //return max(max(f[n-1],g[n-1]),max(f[n],g[n]));
    }
};

删除并获得点数

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        //把所有相同的数字映射在对应下标下,并计算他们的和,意思就是删除这个数所获得的这个数的所有存在之和
        //把零也作为打家劫舍要处理的部分,因为不值得额外处理
        //同样必须把预处理后的数组全部读完

        int n=nums.size();
        int a[20001]={0};
        for(auto e:nums)
        {
            a[e]+=e;
        }

        vector<int> f(20002);
        vector<int> g(20002);

        for(int i=1; i<20002; i++)
        {
            f[i]=g[i-1]+a[i-1];
            g[i]=max(f[i-1],g[i-1]);
        }

        return max(f[20001],g[20001]);
    }
};

优化方法:可以先遍历一遍数组找到最大值,只建立刚好映射最大数字的数组,在数据范围小的时候,这样可以大大减少后续遍历的时间。

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        //把所有相同的数字映射在对应下标下,并计算他们的和,意思就是删除这个数所获得的这个数的所有存在之和
        //把零也作为打家劫舍要处理的部分,因为不值得额外处理
        //同样必须把预处理后的数组全部读完

        int n=nums.size();
        //int a[20001]={0};
        int nums_max=0;
        for(auto e:nums)
        {
            nums_max=max(e,nums_max);
        }
        vector<int> a(nums_max+1);//刚好能够映射max的下标
        for(auto e:nums)
        {
            a[e]+=e;
        }

        vector<int> f(nums_max+2);
        vector<int> g(nums_max+2);

        for(int i=1; i<nums_max+2; i++)
        {
            f[i]=g[i-1]+a[i-1];
            g[i]=max(f[i-1],g[i-1]);
        }

        return max(f[nums_max+1],g[nums_max+1]);
    }
};

粉刷房子

090f084b1c974c7288437cbee5778123.png

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/JEj789/

class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
        int n=costs.size();
        vector<vector<int>> dp(n+1,vector<int>(3));

        for(int i=1; i<n+1; i++)
        {
            //1.这里是用costs的0位置来填dp表的1号位置
            //2.这层三种选择,每种选择都会影响前一种选择
            dp[i][0]=min(dp[i-1][1],dp[i-1][2])+costs[i-1][0];
            dp[i][1]=min(dp[i-1][0],dp[i-1][2])+costs[i-1][1];
            dp[i][2]=min(dp[i-1][0],dp[i-1][1])+costs[i-1][2];
        }

        return min(min(dp[n][0],dp[n][1]),dp[n][2]);//需要用两个min,而不是三个
    }
};

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脆皮骷髏人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值