保研机试之【动态规划】

本文为博客:动态规划解题套路框架 | labuladong 的算法笔记 的笔记

前言

动态规划问题的一般形式就是求最值,求解动态规划的核心问题是穷举。动态规划三要素为:最优子结构、重叠子问题、状态转移方程。首先要判断,该问题是否具有重复子问题,如果有则可以用动态规划求解。动态规划问题存在「重叠子问题」,如果暴力穷举的话效率会很低,所以需要你使用「备忘录」或者「DP table」来优化穷举过程;动态规划只有列出正确的「状态转移方程」,才能正确地穷举。

理解重复子问题:https://leetcode.cn/problems/fibonacci-number/description/

递归算法的时间复杂度怎么计算?就是用子问题个数乘以解决一个子问题需要的时间。

暴力求解(注意树的形状)

会存在很多计算重复的情况,这也是为什么不采用备忘录会导致效率低下,时间复杂度为O(2^{n}),因为子问题个数为2^{n},解决一个子问题需要的时间(加法)为1。

带备忘录的递归解法(注意树的剪枝)

最后就剩类似红色方框的形状:

时间复杂度为O(n),因为子问题个数为n,解决一个子问题需要的时间(加法)为1。

dp 数组的迭代(递推)解法

理解状态转移方程:322. 零钱兑换 - 力扣(LeetCode)

暴力求解

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        if(amount==0){return 0;}
        if(amount<0){return -1;}
        int ans=INT_MAX;
        for(int i:coins){
            int temp=coinChange(coins,amount-i);
            if(temp==-1){continue;}
            ans=min(ans,temp+1);
        }
        if(ans==INT_MAX){
            return -1;
        }
        else{return ans;}
    }
};

直接超时:

带备忘录的递归

class Solution {
public:
    unordered_map<int,int> hmap;
    int coinChange(vector<int>& coins, int amount) {
        if(amount==0){return 0;}
        if(amount<0){return -1;}
        if(hmap.find(amount)!=hmap.end()){
            return hmap[amount];
        }
        int ans=INT_MAX;
        for(int i:coins){
            int temp;
            if(hmap.find(amount-i)!=hmap.end()){
                temp=hmap[amount-i];
            }
            else{
                temp=coinChange(coins,amount-i);
                if(temp==-1){continue;}
                else{hmap[amount-i]=temp;}
            }
            ans=min(ans,temp+1);
        }
        if(ans==INT_MAX){
            return -1;
        }
        else{return ans;}
    }
};

但是!

dp 数组的迭代解法

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> g(10010,amount+1);
        g[0]=0;
        for(int i=1;i<=amount;i++){
            for(auto j:coins){
                if(i-j>=0){
                    g[i]=min(g[i],g[i-j]+1);
                }
            }
        }
        if(g[amount]>amount){return -1;}
        return g[amount];
    }
};

保研机试之【动态规划--最长递增子序列】-CSDN博客 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值