前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >经典算法之贪心算法

经典算法之贪心算法

作者头像
用户3467126
发布2019-11-08 09:32:16
1.6K0
发布2019-11-08 09:32:16
举报
文章被收录于专栏:爱编码爱编码

什么是贪心算法?

  贪心算法,又称贪婪算法(Greedy Algorithm),是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优解出发来考虑,它所做出的仅是在某种意义上的局部最优解。  

贪婪算法是一种分阶段的工作,在每一个阶段,可以认为所做决定是最好的,而不考虑将来的后果。这种“眼下能够拿到的就拿”的策略是这类算法名称的来源。  

贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。所以对所采用的贪心策略一定要仔细分析其是否满足无后效性。

贪心算法的基本思路:

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

贪心算法适用的问题

  贪心策略适用的前提是:局部最优策略能导致产生全局最优解。也就是当算法终止的时候,局部最优等于全局最优。

贪心算法的实现框架

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

while (能朝给定总目标前进一步) { 利用可行的决策,求出可行解的一个解元素;

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

贪心策略的选择

  因为用贪心算法只能通过解局部最优解的策略来达到全局最优解,因此,一定要注意判断问题是否适合采用贪心算法策略,找到的解是否一定是问题的最优解。如果确定可以使用贪心算法,那一定要选择合适的贪心策略;

贪心算法的几个例子

1. 纸币找零问题

假设1元、2元、5元、10元、20元、50元、100元的纸币,张数不限制,现在要用来支付K元,至少要多少张纸币?

很显然,我们很容易就想到使用贪心算法来解决,并且我们所根据的贪心策略是,每一步尽可能用面值大的纸币即可。当然这是正确的,代码如下:

代码语言:javascript
复制
/**     * 钱币找零问题     *     * @param money the money     */    public static void greedyGiveMoney(int money) {        System.out.println("需要找零: " + money);        int[] moneyLevel = {1, 5, 10, 20, 50, 100};        for (int i = moneyLevel.length - 1; i >= 0; i--) {            int num = money/ moneyLevel[i];            int mod = money % moneyLevel[i];            money = mod;            if (num > 0) {                System.out.println("需要" + num + "张" + moneyLevel[i] + "块的");            }        }    }

(1)如果不限制纸币的金额,那这种情况还适合用贪心算法么。比如1元,2元,3元,4元,8元,15元的纸币,用来支付K元,至少多少张纸币?

经我们分析,这种情况是不适合用贪心算法的,因为我们上面提供的贪心策略不是最优解。比如,纸币1元,5元,6元,要支付10元的话,按照上面的算法,至少需要1张6元的,4张1元的,而实际上最优的应该是2张5元的。

(2)如果限制纸币的张数,那这种情况还适合用贪心算法么。比如1元10张,2元20张,5元1张,用来支付K元,至少多少张纸币?

同样,仔细想一下,就知道这种情况也是不适合用贪心算法的。比如1元10张,20元5张,50元1张,那用来支付60元,按照上面的算法,至少需要1张50元,10张1元,而实际上使用3张20元的即可;

(3)所以贪心算法是一种在某种范围内,局部最优的算法。

2.股票问题

题干条件:假设你有一个数组,其中第i个元素是某只股票在第i天的价格。如你最多只获准完成一项交易(即,买一股,卖一股),设计一个算法来寻找最大的利润。注意,你不能在买股票之前卖掉它。

测试样例:

代码语言:javascript
复制
Example 1:
Input: [7,1,5,3,6,4]Output: 5Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.             Not 7-1 = 6, as selling price needs to be larger than buying price.Example 2:
Input: [7,6,4,3,1]Output: 0Explanation: In this case, no transaction is done, i.e. max profit = 0.

Java代码实现:

代码语言:javascript
复制
public static int maxProfit(int[] prices) {        //1.很巧妙的思路 一层循环解决 更新数组里面的最小值 和最大插值        Integer maxProfit = Integer.MIN_VALUE;        Integer minPrice = Integer.MAX_VALUE;        for(Integer price:prices){            minPrice=Math.min(minPrice,price);            maxProfit = Math.max(maxProfit,price-minPrice);        }        return maxProfit<=0?0:maxProfit;    }

参考文档:

https://www.cnblogs.com/xiaozhang2014/p/7783795.html

http://www.pianshen.com/article/5371279467/

推荐阅读

1什么是一致性Hash算法?

2、如何做到接口的幂等性

3、10亿个数字里里面找最小的10个

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱编码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 贪心算法的基本思路:
  • 贪心算法适用的问题
  • 贪心算法的实现框架
  • 贪心策略的选择
  • 贪心算法的几个例子
  • 参考文档:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档