博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2021-06-09
阅读量:3957 次
发布时间:2019-05-24

本文共 3652 字,大约阅读时间需要 12 分钟。

求解最优化的问题常常会有一系列的步骤,而每个步骤往往会面临着选择。

而贪心算法就是这样的算法,它在每一步都做出最优解,也就是说,它总是做出局部最优解,寄希望于通过局部最优解来获得全局最优解。

我们首先举个栗子:调度竞争资源来完成任务,比如我们要利用有限的资源(如一个阶梯教室)来实现任务(举办活动),每个活动的时间不一样,分别有开始时间和就结束时间,拿如何得到最优解呢?

我们看到虽然用动态规划来求解活动选择问题,但是并不需要这么做,我们可以反复选择最早结束的活动,同时保留与此兼容的活动,重复这一过程,直到不再有剩余活动。我们选择了活动结束的最早时间,所以活动结束时间必然是单调递增的,所以我们只需要按照结束时间的单调递增顺序处理所有活动,直到活动结束,每个活动只考察一次。

定理:考虑任何非空子集问题S,a是S中最早结束的活动,所以a必然在S中某个最大兼容活动子集中。

贪心算法往往是这种自顶向下的设计,先做出一个选择,然后再求解下一个问题,而不是自底向上解出许多子问题,然后再做出选择。

在做贪心选择时,我们直接做出当前问题中看起来最优的解,而不是考虑到子问题的解,这也是贪心算法和动态规划的不同之处,在动态规划中,我们往往每一个步骤都求做一个选择,这个选择往往依赖于子问题的解。而在贪心算法中,我们总是做出当时看来最佳的选择,然后再求解剩下唯一的子问题。贪心算法做出选择时可能会依赖于之前的选择或者子问题的解,但是绝对不依赖于将来的选择或者子问题的解。就是我们前面所说的,一个动态规划问题是自底向上的,而一个贪心算法问题是自顶向下的。

下面是几道leetcode题,解法思路都是贪心算法,我用的是python:

1.分配饼干

Leetcode : 455. Assign Cookies (Easy)Input: [1,2], [1,2,3]Output: 2

题目描述:每个孩子都有一个满足度,每个饼干都有一个大小,只有饼干的大小大于一个孩子的满足度,该孩子才会获得满足。求解最多可以获得满足的孩子数量。

思路:因为最小的孩子最容易得到满足,因此先满足最小孩子。给一个孩子的饼干应当尽量小又能满足该孩子,这样大饼干就能拿来给满足度比较大的孩子。

假设在某次选择中,贪心策略选择给第 i 个孩子分配第 m 个饼干,并且第 i 个孩子满足度最小,第 m 个饼干为可以满足第 i 个孩子的最小饼干,利用贪心策略最终可以满足 k 个孩子。假设最优策略在这次选择中给 i 个孩子分配第 n 个饼干,并且这个饼干大于第 m 个饼干。我们发现使用第 m 个饼干去替代第 n 个饼干完全不影响后续的结果,因此不存在比贪心策略更优的策略,即贪心策略就是最优策略。

class Solution:   def findContentChildren(self, g, s):       """       :type g: List[int]       :type s: List[int]       :rtype: int       """       g.sort()       s.sort()       i=j=res=0       while i

一支弓箭可以沿着x轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。

思路:从左往右投飞镖,并且在每次投飞镖时满足以下条件:

1.左边已经没有气球了;
2.本次投飞镖能够刺破最多的气球。

class Solution:   def findMinArrowShots(self, points):       """       :type points: List[List[int]]       :rtype: int       """        points.sort(key = lambda x:(x[0],x[1]))       n = len(points)       if n == 0:return 0       S = points[0][0]       E = points[0][1]       res = 1       for i in range(1,n):           if E>points[i][1]:               E = points[i][1]           elif S
E: res += 1 S = points[i][0] E = points[i][1] return res

3.股票的最大收益

Leetcode : 122. Best Time to Buy and Sell Stock II (Easy)

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

input: [7,1,5,3,6,4]output: 7

思路: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。

随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

对于 [a, b, c, d],如果有 a <= b <= c <= d ,那么最大收益为 d - a。而 d - a = (d - c) + (c - b) + (b - a) ,因此当访问到一个 prices[i] 且 prices[i] - prices[i-1] > 0,那么就把 prices[i] - prices[i-1] 添加加到收益中,从而在局部最优的情况下也保证全局最优。

class Solution:   def maxProfit(self, prices):       """       :type prices: List[int]       :rtype: int       """       profit = 0       for i in range(len(prices)-1):           if prices[i+1]>prices[i]:               profit += (prices[i+1]-prices[i])       return profit

4.种植花朵

Leetcode : 605. Can Place Flowers (Easy)Input: flowerbed = [1,0,0,0,1], n = 1Output: True

假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?能则返回True,不能则返回False。

示例 1:

input: flowerbed = [1,0,0,0,1], n = 1
output: True

思路:自己想吧,不难的

class Solution:   def canPlaceFlowers(self, flowerbed, n):       """       :type flowerbed: List[int]       :type n: int       :rtype: bool       """       flowerbed.append(0)       flowerbed.insert(0,0)       num = 0       res = 0       for i in range(len(flowerbed)):           if flowerbed[i] == 0:               num += 1           else :               num = 0           if num == 3:               res += 1               num = 1       return res>=n

转载地址:http://wexzi.baihongyu.com/

你可能感兴趣的文章
codeforces——1097B,Petr and a Combination Lock(搜索)
查看>>
杭电ACM——2064,汉诺塔III(递推)
查看>>
杭电ACM——2065,"红色病毒"问题(思维)
查看>>
北大ACM——2385,Apple Catching(DP)
查看>>
杭电AM——2072,单词数(暴力)
查看>>
杭电ACM——2073,无限的路(思维)
查看>>
杭电ACM——2069,Coin Change(DP)
查看>>
杭电ACM——2074,叠筐
查看>>
北大ACM——3616,Milking Time(DP)
查看>>
杭电ACM——2076,夹角有多大
查看>>
牛客练习赛43——B Tachibana Kanade Loves Probability(暴力,思维)
查看>>
牛客第十七届上海大学程序设计春季联赛——E CSL 的魔法(贪心)
查看>>
杭电ACM——1028,Ignatius and the Princess III(母函数)
查看>>
杭电ACM——1171,Big Event in HDU(母函数)
查看>>
杭电ACM——6491,时间间隔(思维)
查看>>
杭电AC——1085,Holding Bin-Laden Captive!(母函数)
查看>>
杭电ACM——2110,Crisis of HDU(母函数)
查看>>
杭电AM——2152,Fruit(母函数)
查看>>
杭电ACM——2566,统计硬币(DP)
查看>>
堆栈(数据结构)
查看>>