贪心算法Python等各语言实现详解(题目解析&代码注释超详细),强烈建议新手入门看!

一、贪心算法理论基础(必看)

(1)贪心算法(greedy algorithm)概念

贪心算法(greedy algorithm),又称贪婪算法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择, 从而希望导致结果是最好或最优的算法。比如在旅行推销员问题中,如果旅行员每次都选择最近的城市,那这就是一种贪心算法。
—————— 摘自维基百科


注释:可以理解为贪心算法每一步都做出当前最正确的决定(局部最优解),通过堆叠局部最优解得到全局最优解。

一个具象的例子:贪心算法像极了父母为我们设想的一生,从小学起就好好学习,小学上一个重点初中(局部最优解1),再通过重点初中上到重点高中(局部最优解1->2),再通过重点高中上到985或海外名校(局部最优解1->2->3),再通过985或海外名校上到藤校硕博、公司高管或政府高官等走上人生巅峰(全局最优解1->2->3->4)。

(2)贪心算法的基本要素

①贪心选择
贪心选择是指所求问题的全局最优解可以通过不断堆叠局部最优解得到。这是贪心算法可行的基本条件,也是贪心算法与动态规划算法的主要区别。
②最优子结构
当一个问题的最优解包含子问题的最优解时,称此问题具有最优子结构的性质。贪心算法的每一次选择都对结果产生直接的影响,而动态规划不是;贪心算法对每个子问题都做出当前最优的选择,并且不能回退,动态规划则不是,动态规划会根据从前的选择结果对当前进行选择,有回退功能。

贪心算法一般用来解决一维的问题,动态规划一般解决多维问题。

二、贪心算法题目(Python、C++、C、JAVA实现)

(1)初级贪心算法(LeetCode 455.分发饼干为例)

我的个人感觉是,这类问题能自己解决出来,但你不知道自己用了贪心算法或者贪心策略比较明显。
题目原题链接

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
输入: g = [1,2,3], s = [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:
输入: g = [1,2], s = [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.

题目解析:在这里采用贪心策略的思想,让孩子们按胃口大小排成队,胃口小的在前面,饼干按大小也摞好,小的在上面,每次给队头的孩子一个能满足他胃口且尽可能小的饼干(这个过程就是求局部最优解的过程),吃到饼干的队头孩子就离开队伍,直到饼干发完或者队伍没人即每个孩子都吃到饼干(:这是通过局部最优解堆叠求得全局最优解)
Python代码

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()#列表的排序命令,默认从小到大排序。将孩子按胃口大小排成队
        s.sort()#把饼干也从小到大摞起来
        child=0#统计吃到饼干的孩子数
        i=0;j=0;
        while i<len(g) or j<len(s):#设置循环结束条件
            if s[j]>=g[i]:#如果第j个饼干刚好可以满足第i个孩子
                child+=1
                i+=1
                j+=1
            else:#如果不能,换下一个饼干试试能不能满足这个孩子
                j+=1
        print(child)

C++代码

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

C语言

int cmp(const void* a, const void* b)
{
    return *(int*)a - *(int*)b;  //升序
}

int findContentChildren(int* g, int gSize, int* s, int sSize)
{
    qsort(g,gSize,sizeof(int),cmp);
    qsort(s,sSize,sizeof(int),cmp);  //将数组g和s 从小到大升序排列

    //二重指针
    int gi = 0;
    int si = 0;

    int cnt = 0;

    while(gi<gSize && si<sSize)
    {
        if(s[si] >= g[gi])   //如果满足孩子
        {
            gi++;  //则遍历下一个孩子
            cnt++; //可满足的孩子数+1
        }
        si++; //不论是否满足孩子,饼干都+1
    }

    return cnt;
}

JAVA代码

class Solution {
        public int findContentChildren(int[] g, int[] s) {

            if (g == null || s == null || g.length == 0 || s.length == 0) return 0;
            Arrays.sort(g);
            Arrays.sort(s);

            int idx_child = 0;
            int idx_cookie = 0;
            int count = 0;

            while (idx_child < g.length) {

                // 如果饼干已经发放完, 则结束
                if (idx_cookie > s.length-1) return count;

                while (idx_cookie < s.length) {

                    if (s[idx_cookie] >= g[idx_child]) { // 如果最小的饼干能够满足最小的胃口,则发放
                        idx_child++;
                        idx_cookie++;
                        count++;

                        // 如果孩子已经选择完.直接返回发到饼干的孩子个数
                        if (idx_child > g.length-1) return count;

                    }else { // 否则我们继续寻找最小的饼干.
                        idx_cookie++;
                    }
                }
            }

            return count;
        }
    }

(2)进阶贪心算法(待完善)

中高阶例题还需要完善~
建议先把贪心算法的概念和贪心策略理解清楚然后通过做题加深理解,慢慢来~~有问题或者建议和意见都可直接评论,博主敞亮人~

(1)高阶贪心算法(待完善)

三、贪心算法、动态规划、标准分治算法比较(拓展)

有待继续完工~

  • 12
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值