贪心算法

贪心算法

  • 贪心算法Greedy
  • 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的解法。
  • 贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。
  • 贪心法可以解决一些最优化问题,如:求图中的最小生成树,求哈夫曼编码等。然而对于工程和生活中的问题,贪心法一般不能得到我们要求的答案。
  • 一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好办法,由于贪心法的高效性以及其求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。

实战题目

零钱兑换
当硬币可选集合固定:Coins = [20, 10, 5, 1]

求最少可以几个硬币拼出总数。 比如 total = 36

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {

        //Coin required store for amount from 0 to amount.
        int coin_required[amount+1] = {0};

        //Calculate for coin required for amount 1 till amount.
        for(int i = 1; i <= amount; i++ )
        {
            //To start with set the min coin value to high .
            int min_coin_required  = 1e8;
            for(int c = 0; c < coins.size(); c++ )
            {
                int coin_value = i - coins[c];

                //Coin value becomes -ve after giving the coin. 
                //Don't use the coin, cotinue
                if(coin_value < 0)
                    continue;

                else if(coin_value == 0)
                {
                    //Got perfect coin match for the amount.
                    min_coin_required = 1;
                    break;
                }
                else
                {
                    //Post using the coin_value check for remaining 
                    //amount, if remaining amount can't be given, no point in 
                    //proceeding with this coin value.
                    if(coin_required[coin_value] != 1e8)
                    {
                        //Existing solution is available add current coin in the existing solution.  
                        min_coin_required =  min(min_coin_required, coin_required[coin_value] + 1);
                    }
                }
            }

            //Set the value for amount i.
            coin_required[i] = min_coin_required;
        }

        //Coins are not available for this amount.
        if(coin_required[amount] == 1e8)
            return -1;

        return coin_required[amount];
    }
};

适用贪心算法的场景

  • 简单地说,问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。这种子问题最优解成为最优子结构。
  • 贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会抱保护以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。

LeetCode实战练习

柠檬水找零

class Solution {
public:
    bool lemonadeChange(const vector<int>& bills) {
        int five = 0, ten = 0;
        for (const auto& bill : bills)
            if (bill == 5) five++;
            else if (bill == 10 && 0 < five) --five, ++ten;
            else if (0 < ten && 0 < five) --five, --ten;
            else if (2 < five) five-=3;
            else return false;
        return true;
    }
};

买卖股票的最佳时机-II

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        //快慢指针标记
        int i=0,j=1,sum=0;
        //判断vector大小
        if(prices.size()<=1)
        return 0;

        //两个指针一直紧挨在一起,只有j的值大于i的值时,就把差值加入sum中
        while(j<prices.size()){
            if(prices[j]-prices[i]>0)
                sum+=(prices[j]-prices[i]);

                i++;
                j++;
        }
        return sum;
    }
};

分发饼干

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int j = 0;
        int i = 0;
        while(i < g.size() && j < s.size()){
            if(g[i] <= s[j]){
                i++;j++;
            } else {
                j++;
            }
        }
        return i;
    }
};

模拟行走机器人

class Solution {
public:
    void left(char& c)
    {
        if(c == 'U') c = 'L';
        else if(c == 'L') c = 'D';
        else if(c == 'D') c = 'R';
        else c = 'U';
    }

    void right(char& c)
    {
        if(c == 'U') c = 'R';
        else if(c == 'R') c = 'D';
        else if(c == 'D') c = 'L';
        else c = 'U';
    }
    int distance(pair<int,int> curr_point)
    {
        return curr_point.first * curr_point.first + curr_point.second * curr_point.second;
    }
    struct pair_hash
    {
        template <class T1, class T2>
        std::size_t operator () (std::pair<T1, T2> const &pair) const
        {
            std::size_t h2 = std::hash<T2>()(pair.second);

            return h1 ^ h2;
        }
    };
    int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {

        char c = 'U';
        pair <int,int> curr_point = make_pair(0,0);
        unordered_set < pair<int,int> , pair_hash> obs;
        int dist = 0;
        for(auto w: obstacles) obs.insert(make_pair(w[0],w[1]));
        for(int i = 0; i < commands.size(); ++i)
        {
            if(commands[i] == -1) right(c);
            else if(commands[i] == -2) left(c);
            else
            {
                bool obstacle = false;
                for(int j = 1; j <= commands[i] and not obstacle; ++j)
                {
                    if(c == 'R')
                    {
                        if(obs.find(make_pair(curr_point.first+1,curr_point.second)) != obs.end())
                        {

                            obstacle = true;
                        }
                        else curr_point.first += 1;
                    }
                    else if(c == 'U')
                    {

                       if(obs.find(make_pair(curr_point.first,curr_point.second+1)) != obs.end())
                        {

                            obstacle = true;
                        }
                        else
                        {
                            curr_point.second += 1;
                        }
                    }
                    else if(c == 'D')
                    {

                        if(obs.find(make_pair(curr_point.first,curr_point.second-1)) != obs.end())
                        {

                            obstacle = true;
                        }
                        else curr_point.second -= 1;
                    }
                    else if(c == 'L')
                    {
                        if(obs.find(make_pair(curr_point.first-1,curr_point.second)) != obs.end())
                        {

                            obstacle = true;
                        }
                        else curr_point.first -= 1;
                    }
                    dist = max(dist,distance(curr_point));
                }
            }
        }
        return dist;        
    }
};

跳跃游戏

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int i,minjump=0;
        for(i=nums.size()-2;i>=0;i--){
            minjump++;
            if(nums[i]>=minjump)minjump=0;
        }
        if(minjump==0)return true;
        else return false;
    }
};

原文链接: https://www.cnblogs.com/liugangjiayou/p/12398818.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    贪心算法

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/371006

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月3日 上午10:31
下一篇 2023年3月3日 上午10:32

相关推荐