和你一起刷算法-LeetCode刷题之“贪”(一)

五大常用算法:

1、递归与分治:直接或者间接不断反复调用自身来达到解决问题的方法。这就要求原始问题可以分解成相同问题的子问题。主要解决的是阶乘、斐波纳契数列、汉诺塔类似问题。

2、动态规划:基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

与分治不同在于:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。

3、贪心算法:理解的话就是从字面意思理解“贪”,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅仅是在某种意义上的局部最优解

4、回溯法:回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。通常与“剪枝”放在一起使用。

5、分支限界法:和回溯法相似,也是一种搜索算法,但回溯法是找出问题的许多解,而分支限界法是找出原问题的一个解。或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解。

上面五种常用算法每种算法其实都有自己解题领域和思想,同样也拥有自己的解题方式和模板提供参考。本章只针对贪心算法进行总结和归纳,其他几种陆陆续续也会整理出来🤗。

五常算法之三之贪心

先举个栗子🌰

举一个最简单的例子:小明和小王喜欢吃苹果,小明可以吃五个,小王可以吃三个。已知苹 果园里有吃不完的苹果,求小明和小王一共最多吃多少个苹果。在这个例子中,我们可以选用的 贪心策略为,每个人吃自己能吃的最多数量的苹果,这在每个人身上都是局部最优的。又因为全 局结果是局部结果的简单求和,且局部结果互不相干,因此局部最优的策略也同样是全局最优的 策略。

解题实现框架:

从问题的某一初始解出发;

while (能朝给定总目标前进一步)

{ 

      利用可行的决策,求出可行解的一个解元素;

}

由所有解元素组合成问题的一个可行解;

贪心算法的基本思路:

  • 建立数学模型来描述问题
  • 把求解的问题分成若干个子问题
  • 对每个子问题求解,得到子问题的局部最优解
  • 把子问题的解局部最优解合成原来问题的一个解

贪心算法存在的问题:

  • 不能保证求得的最后解是最佳的
  • 不能用来求最大值或最小值的问题
  • 只能求满足某些约束条件的可行解的范围

LeetCode刷题

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.

题解:

图一

因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。

为了尽量使得剩下的饼干可 以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的、且大小最小的饼干给这 个孩子。

满足了这个孩子之后,我们采取同样的策略,考虑剩下孩子里饥饿度最小的孩子,直到 没有满足条件的饼干存在。

简而言之,这里的贪心策略是,给剩余孩子里最小饥饿度的孩子分配最小的能饱腹的饼干。

至于具体实现,因为我们需要获得大小关系,一个便捷的方法就是把孩子和饼干分别排序。 这样我们就可以从饥饿度最小的孩子和大小最小的饼干出发,计算有多少个对子可以满足条件。

注意: 对数组或字符串排序是常见的操作,方便之后的大小比较。
注意:在之后的讲解中,若我们谈论的是对连续空间的变量进行操作,我们并不会明确区分数组和字符串,因为他们本质上都是在连续空间上的有序变量集合。一个字符串“abc”可以被看作一 个数组 [‘a’,‘b’,‘c’]。

代码:

套用模板

从问题的某一初始解出发;

while (能朝给定总目标前进一步)

{ 

      利用可行的决策,求出可行解的一个解元素;

}

由所有解元素组合成问题的一个可行解;
class Solution {    
    public int findContentChildren(int[] g, int[] s) {        
        /**         
          * 排序的目的是贪心         
          * 为了找到饭量最小的那个孩子先喂饱         
          * 同时找到饼干大小排序方便拿取实现最恰当的饼干喂给最恰当的孩子的最佳实现         
          */        
        Arrays.sort(g);        
        Arrays.sort(s);        
        int child = 0;        
        int cook = 0;        
        while(child < g.length && cook <s.length){            
            if(g[child] <= s[cook]){                
                //可行解  吃饱一个继续喂下个                
                ++child;            
            }            
            //往下遍历饼干            
            ++cook;        
        }        
        return child;    
    }
}
图二

第二题快速导航:

135. 分发糖果

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

你需要按照以下要求,帮助老师给这些孩子分发糖果:

每个孩子至少分配到 1 个糖果。
相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?

示例 1:

输入: [1,0,2]

输出: 5

解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。

示例 2:

输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。   
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。

题解:

做完了题目 455,你会不会认为存在比较关系的贪心策略一定需要排序或是选择?

虽然这一 道题也是运用贪心策略,但我们只需要简单的两次遍历即可:

1、把所有孩子的糖果数初始化为 1;

2、先从左往右遍历一遍,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的 糖果数加 1;

3、再从右往左遍历一遍,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数 不大于右边孩子的糖果数,则左边孩子的糖果数更新为右边孩子的糖果数加 1。

通过这两次遍历, 分配的糖果就可以满足题目要求了。这里的贪心策略即为,在每次遍历中,只考虑并更新相邻一 侧的大小关系。

在样例中,我们初始化糖果分配为 [1,1,1],第一次遍历更新后的结果为 [1,1,2],第二次遍历 更新后的结果为 [2,1,2]。

代码:

套用模板

从问题的某一初始解出发;

while (能朝给定总目标前进一步)

{ 

      利用可行的决策,求出可行解的一个解元素;

}

由所有解元素组合成问题的一个可行解;
class Solution {    
    public int candy(int[] ratings) {        
        int size = ratings.length;        
        if(size < 2){            
            return size;        
        }        
        int[] array = new int[size];        
        //初始化数组内数字为1        
        for(int i = 0;i<size;i++){            
            array[i] = 1;        
        }        
        //正向对比   左比右        
        for(int n = 1;n<size;n++){            
            if(ratings[n-1] < ratings[n]){                
                //右子大 则右子比左子加一                
                array[n] = array[n-1] + 1;            
            }        
        }        
        //反向对比 右比左        
        for(int m = size -1; m>0;m--){            
                if(ratings[m-1] > ratings[m]){                
                    //左子大 因为有上面一层循环保证比较 右子比左子大则右子比左子多                
                    //现在需要保证 左子大则左子要比右子多  至于取数则在自己已有数据上和右子加一作对比取大值                
                    array[m-1] = Math.max(array[m-1],array[m]+1);            
                }        
        }        
        int sum = 0;        
        for(int q = 0;q<size;q++){            
            sum = sum + array[q];        
        }        
        return sum;    
    }
}
图三

本文主要是针对贪心算法中的分配问题做了解析总结(点比较),贪心算法还有一种题型是区间问题(段比较),区间问题总结讲再下一博文总结归纳,Thanks♪(・ω・)ノ。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 贪心算法 贪心选择:通过一系列的局部最优解达到整体最优解。 前提:必须证明贪心选择可以达到最优解:先证明整体最优解...
    RayRaymond阅读 1,265评论 0 0
  • 1、贪心算法简介 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体...
    AKyS佐毅阅读 2,093评论 0 0
  • 汇总几个常见的贪心算法实现的问题 概述 IPO(最大投资收益) 金砖最小分割代价 会议室相关问题 分发糖果 柠檬水...
    yaco阅读 1,366评论 0 2
  • 2019 iOS面试题大全---全方面剖析面试2018 iOS面试题---算法相关1、七种常见的数组排序算法整理(...
    Theendisthebegi阅读 7,024评论 1 17
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,482评论 16 22