算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)

阅读完本文,你将对贪心算法有初步的认知和刷题能力。

贪心算法

用一句话概括:每一步都选局部最优解。

对于结果是不是最优解并不关心。因为对于全局来说,局部的每一步最优解累计起来,可能是最优解,也可能不是最优解。

因为贪心算法没有固定的模板,只是一种思想,所以本文收录了几道简单和中等难度的题目,用于认识和理解贪心算法。

贪心算法和贪吃蛇

我们用贪吃蛇的例子来感受贪心算法:

如果每一步都选择最优解,蓝色路线是贪心算法选出来的路线,而作为人类,我们一眼就能看出,红色路线是最优解。这个例子就是贪心算法不是最优解的例子。

Easy / 简单

Leetcode 121 - 买卖股票的最佳时机

Leetcode 121 - 买卖股票的最佳时机

首先来一道HOT100上贪心算法板块的简单题目。

本题的想法是,找最低的价格买入,找最高的价格卖出,求局部最优解,以获得全局最优解。

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int minPrice = INT_MAX;
        int maxProfit = 0;
        for(int i = 0;i<n;i++){
            minPrice = min(minPrice,prices[i]);
            maxProfit = max(maxProfit,prices[i] - minPrice); 
        }
        return maxProfit;
    }
};

Leetcode 455 - 分发饼干

Leetcode 455 - 分发饼干

两列数据按照顺序排列后,注意越界判断,可以写在for循环里:

cpp 复制代码
 for (; ck < cookies.size() && cd < childs.size(); ck++)

也可以写在if里,但注意要在判断大小之前。如下:

cpp 复制代码
class Solution {
public:
    int findContentChildren(vector<int>& childs, vector<int>& cookies) {
        sort(cookies.begin(), cookies.end(), less<int>());
        sort(childs.begin(), childs.end(), less<int>());
        int ck = 0;
        int cd = 0;
        for( ;ck<cookies.size();ck++){
            if(cd <childs.size() && childs[cd] <= cookies[ck]){
                cd++;
            }
        }
        return cd;
    }
};

Leetcode 860 - 柠檬水找零

Leetcode 860 - 柠檬水找零

找零场景分为三种情况,顾客支付5,10,20 。5和10都比较简单,注意20时,当10的值为0时,考虑找零3张5 。

cpp 复制代码
class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int five = 0;
        int ten = 0;
        for (int bill : bills) {
            if (bill == 5) {
                five++;
            } else if (bill == 10) {
                ten++;
                if (five) {
                    five--;
                } else {
                    return false;
                }
            } else {
                if (ten && five) {
                    ten--;
                    five--;
                } else if (five >= 3) {
                    five -= 3;
                } else {
                    return false;
                }
            }
        }
        return 1;
    }
}
;

Medium / 中等

Leetcode 376 摆动序列

cpp 复制代码
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n = nums.size();
        if(n<2){
            return n;
        }
        int preDiff = nums[1] - nums[0];
        int res = preDiff != 0? 2:1;
        for(int i = 2;i<n;i++){
            int diff = nums[i] - nums[i-1];
            if((diff > 0 && preDiff <=0)|| (diff < 0 && preDiff >=0)){
                res++;
                preDiff = diff;
            }
        }
        return res;
    }
};

Leetcode 738 - 单调增加的数字

首先尝试暴力法:

cpp 复制代码
class Solution {
public:
    bool isMono(int n){
        int pre = 10;
        while(n){
            int dig = n % 10;
            if(dig > pre) return false;
            pre = dig;
            n = n / 10;
        }
        return true;
    }
    int monotoneIncreasingDigits(int n) {
       while(n){
            if(isMono(n)){
                return n;
            }
            n--;
       } 
       return 0;
    }
};

发现不转换为字符串,是非常难解决的,尝试转换为字符串,例如85,最后结果是79,可以发现是if(si-1>si),需要把si-1--,且si=9。

再多举几个例子,例如8765,其中的过程是:8765->8759->8699->7999。故写出以下代码:

cpp 复制代码
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string s = to_string(n);
        for(int i = s.size()-1;i>0;i--){
            if(s[i-1]> s[i]){
                s[i-1]--;
                for(int j = i;j<s.size();j++) s[j] = '9';
            }
        }
        return stoi(s);
    }
};
相关推荐
coder!mq22 分钟前
说几个常见的语法糖?
java·开发语言·算法
不爱学英文的码字机器1 小时前
推荐算法梳理,六种主流模型与九步训练流程
算法·机器学习·推荐算法
白狐_7982 小时前
408数据结构第5章:树与二叉树②——遍历、线索树、森林与哈夫曼
数据结构·算法·深度优先
致Great5 小时前
科研人的 AI,不该只回答问题:我用字节TraeWork 跑了一遍真实研究任务
算法
纵有疾風起5 小时前
线性表的定义与基本操作 — 从逻辑结构到 ADT 接口
数据结构·算法·408·线性表·adt
测试_AI_一辰6 小时前
AI Agent 评测最隐蔽的坑-记忆
人工智能·算法·ai·自动化·ai编程
lucas_AI6 小时前
给YOLO检测器插 LoRA,'插对地方'比'插什么'更要命
人工智能·算法
LuminousCPP6 小时前
数据结构-时间与复杂度|时间/空间复杂度 + 两道力扣练习 + 二分查找复盘
c语言·数据结构·经验分享·算法·leetcode
Nil2087 小时前
leetcode 三数之和
数据结构·算法·leetcode
小小龙学IT7 小时前
C++ std::vector 底层实现深度解析:内存布局、扩容策略、移动语义与迭代器失效
开发语言·c++·算法