文章目录

  • 贪心算法
    • 1、分发饼干问题(力扣455)
    • 2、无重叠区间(力扣435)
    • 3、分发糖果(力扣135)
    • 4、种花问题(力扣605)
    • 5、用最少数量的箭引爆气球(力扣452)
    • 6、划分字母区间(力扣763)
    • 7、买卖股票的最佳时机(力扣122)
    • 8、根据身高重建队列(力扣406)
    • 9、非递减数列(力扣665)

贪心算法

1、贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择,就能得到问题的答案。
2、贪心算法需要充分挖掘题目中条件,没有固定的模式,解决有贪心算法需要一定的直觉和经验。
3、贪心算法不是对所有问题都能得到整体最优解。能使用贪心算法解决的问题具有 无后效性,即某阶段状态一旦确定,就不收后阶段决策的影响

1、分发饼干问题(力扣455)

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j]>= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

> 示例:

输入: g = [1,2,3], s = [1,1]
输出: 1
解释: 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 所以你应该输出1。

def hand_cookies(g:list, s:list):  # g-->胃口,s-->饼干尺寸g.sort()   # 将胃口值和并饼干尺寸按升序排序s.sort()child, cookie = 0, 0ans = 0while child < len(g) and cookie < len(s):if g[child] <= s[cookie]:  # 如果剩下的最小的饼干能满足剩下胃口最小的孩子ans += 1child += 1   # 移到下一个孩子cookie += 1   # 满足当前胃口,该饼干就已分配,到下一个;没满足当前胃口,此饼干作废,也到下一个饼干return ans

思路分析
1、if g[child] <= s[cookie]: child += 1 # 如果剩下的最小的饼干能满足剩下胃口最小的孩子,此孩子得到满足,轮到下一个孩子
2、cookie += 1 # 无论当前饼干是否满足,都移动到下一个

2、无重叠区间(力扣435)

给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。

示例 1:

输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3]后,剩下的区间没有重叠。

示例 2:

输入: intervals = [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2]
来使剩下的区间没有重叠。

def eraseOverlapInterval(intervals):if not intervals:     # 空区间return 0# 将区间按结束值排序。因为区间结束越早,留给后面区间的空间越多,越有可能得到最多数量的无重复区间intervals = sorted(intervals,key=lambda x : x[1])ans = 0end = intervals[0][1]    # 初始化end为第一个元素的end值for i in range(1,len(intervals)):# 如果当前起始值< 前一个的end值,那么当前区间会被踢剔除。为什么一定剔除这个呢?有没有可能剔除的时此区间之后的?# ---不会,因为当前区间时后面区间中结束值最小的。if end > intervals[i][0]:ans += 1else:end = intervals[i][1]return ans

3、分发糖果(力扣135)

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
1)每个孩子至少分配到 1 个糖果。
2)相邻两个孩子评分更高的孩子会获得更多的糖果。
3)请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1

输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2

输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

 def candy(ratings):k = len(ratings)ans = [1]*kfor i in range(1,k):if ratings[i] > ratings[i-1]:    # 右比左大ans[i] = ans[i-1] + 1for i in range(k-2,-1,-1):if ratings[i] > ratings[i+1]:    # 左比右大ans[i] = max(ans[i+1]+1, ans[i])return sum(ans)

思路分析
先从左往右遍历,逐步保证,右边比左边分数高的,获得更多糖果。再从左往右遍历。

ans[i] = max(ans[i+1]+1, ans[i])

这里注意,要取最大值。因为有可能,左边已经比右边大了

4、种花问题(力扣605)

假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false。

示例

输入:flowerbed = [1,0,0,0,1], n = 1 输出:true

def canPlaceFlower(flowerbed: List[int],n:int) -> bool:flowerbed = [0] + flowerbed + [0]count = 0for i in range(1,len(flowerbed)-1):if flowerbed[i-1] == flowerbed[i] == flowerbed[i+1]:flowerbed[i] = 1count += 1if count >= n:return Truereturn False

思路分析
1、flowerbed = [0] + flowerbed + [0]
这里是为了排除边界情况的影响

5、用最少数量的箭引爆气球(力扣452)

在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。

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

给你一个数组 points ,其中 points [i] = [xstart,xend] ,返回引爆所有气球所必须射出的最小弓箭数。

示例 :

输入:points = [[10,16],[2,8],[1,6],[7,12]]
输出:2
解释:对于该样例,x = 6 可以射爆[2,8],[1,6] 两个气球,以及 x = 11 射爆另外两个气球

def findMinArrowShots(points:List[List[Int]])-> int:if not points:return 0points = sorted(points, key=lambda x: x[1])ans = 1end = point[0][1]for i in range(1,len(points)):if points[i][0] > end:ans += 1end = points[i][1]return ans

6、划分字母区间(力扣763)

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。

示例:

输入:S = “ababcbacadefegdehijhklij”
输出:[9,7,8]
解释:划分结果为 “ababcbaca”,“defegde”, “hijhklij”。 每个字母最多出现在一个片段中。

【思路】:先把每个字母出现的最后的位置存储起来,再遍历字符串

def partitionLabels(s):dict_ = {}for i in range(len(s)):   # 存取每个字母出现的最大索引位置dict[s[i]] = ians = []start = 0   # 要存取的是字符串片段的长度,故需要end,start两个指针end = dict_[s[0]]for i in range(len(s)):if i < end:end = max(dict_[s[i+1]], end)else:    # i >= endans.append(end - start + 1)if i+1 < len(s):end = dict_[s[i+1]]start = i+1return ans

7、买卖股票的最佳时机(力扣122)

给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。
在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。
返回 你能获得的 最大 利润 。

示例:

输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3

def maxProfit(self, prices):ans = 0for i in range(1, len(prices)):if prices[i] > prices[i-1]:ans += prices[i] - prices[i-1]return ans

思路分析
1、每次保证当前解为局部最优解,从而保证得到的解是整体最优
贪心算法
2、遍历从1开始,一次比较当天与前一天利润。

8、根据身高重建队列(力扣406)

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。
请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

示例:

输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
解释:
编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。
编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。
编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。
编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。
编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。


def reconstructQueue(people):people = sorted(people, key = lambda x: (-x[0],x[1]))ans = []for item in people:ans.insert(item[1],item)return ans

思路分析
1、因为条件是从高往低,那么我们要先固定高的,再来插入矮的
2、创建ans,从高往低排列,身高相同时,只需要将该身高插入列表对应的位置即可。对应位置几位item[1]

9、非递减数列(力扣665)

给你一个长度为 n 的整数数组 nums ,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。
我们是这样定义一个非递减数列的: 对于数组中任意的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。

示例:

输入: nums = [4,2,3]
输出: true
解释: 你可以通过把第一个 4 变成 1 来使得它成为一个非递减数列。

def checkPossibility(nums):count = 0for i in range(1,len(nums)):if nums[i] < nums[i-1]:count += 1    # 一定要调if nums[i] >= nums[i-2] or i == 1:nums[i-1] = nums[i]else: nums[i] = nums[i-1]if count >= 2:return Falsereturn True

思路分析
要保证整个递增,则只需要保证每三个连续的元素是递增的即可。
因为之多改变一个元素,我们初始化一个count用于记录改变的次数。

只移动一个元素,由以上三种关系。
1)nums[i-2] < nums[i],这时,看上去,我们选择将nums[i-1] = nums[i]或者nums[i] = nums[i-2]似乎都是可以的。但是,我们从左往右遍历,前面的元素值越小,留给后面的元素的范围就越大,就越有可能满足“非递减数列”的要求。因此,这种情况,我们应该令nums[i-1] = nums[i]

2)nums[i-2] >nums[i],这种情况我们只能让nums[i] = nums[i-1],因为只有这样满足要求

3)边界情况分析:因为是从左往右去元素,我们只需要考虑左边界。
即只用考虑nums[0] > nums[1]的情况,因为要尽可能给后面的元素更大的范围,所以我们选择将值大的调小,与第一种情况1)道理相同。
反例:nums = [4,1,2,3],就只能把nums[0]调小,使其与nums[1]相等。

python贪心算法相关推荐

  1. python贪心算法最短路径_dijkstra算法(贪心算法)——解决最短路径问题

    最短路径 给定一张带权图和其中的一个点(作为源点),求源点到其余顶点的最短路径 基本思想 1)源点u,所有顶点的集合V,集合S(S中存有的顶点,他们到源点的最短路径已经确定,源点u默认在S中),集合V ...

  2. python贪心算法几个经典例子_关于贪心算法的一些探讨、经典问题的解决和三种典型的贪心算法算法(哈弗曼,Kruskal,Prim)的Python实现。...

    贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解. 贪心算法不是对所有问题都能得到整体最优解,关键是 ...

  3. python换零钱_黄哥Python, 贪心算法解决换零钱问题

    下面的文字来源于维基百科 贪心算法(英语:greedy algorithm) 又称贪婪算法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法.比如 ...

  4. 农夫过河——python贪心算法实现

    1.问题描述: 一个农夫在河的西岸带了一匹狼.一只羊和一棵白菜,他需要把这三样东西用船带到河的东岸.然而,这艘船只能容下农夫本人和另外一样东西.如果农夫不在场的话,狼会吃掉羊,羊也会吃掉白菜. 2.问 ...

  5. 会议室日程安排问题(python贪心算法)

    会议室日程安排问题(最少需要多少个会议室) 按照贪心算法,此问题可以得到最优解!原来是按结束时间排序,但这样的话并不是最少的会议室数(下面有反例)而要得到最少的会议室数,需要将议程时间按开始时间排序. ...

  6. Python贪心算法解决收银员找零问题

    场景描述 在超市结账时,假设只有1分.5分.1角.3角.5角.1元的硬币,如果需要找零钱,给定需要找的零钱数目,使收银员找给顾客的硬币数量最少,运行程序如图: 知识补充  贪心算法是指在当前问题求解中 ...

  7. python贪心算法最短路径_贪心算法2-单源最短路径

    1.问题分析 给定有向带权图G = (V, E),其中每条边的权是非负实数.此外,给定V中的一个顶点u,称为源点.现在要计算从源到所有其它各顶点的最短路径,这里的路径指的是路径上各边的权值之和. 求单 ...

  8. python贪心算法最短路径_贪心算法---最短路径问题

    一,贪心算法的设计思想 • 从问题的某一个初始解出发逐步逼近给定的目标,每一步都作一个不可回溯的决策,尽可能地求得最好的解.当达到某算法中的某一步不需要再继续前进时,算法停止. 二,贪心算法的基本性质 ...

  9. python贪心算法求删数问题_贪心算法删数问题

    删数问题 给定n位正整数a,去掉其中任意k个数字后,剩下的数字按原次序排列组成一个新的正整数.对于给定的n和k,设计一个算法,找出剩下数字组成的新数最少的删数方案. 输入示例: 178543 4 输出 ...

  10. python贪心算法——以“修理牛棚”题目为例

    [USACO1.3]修理牛棚 Barn Repair 题目描述 在一个月黑风高的暴风雨夜,Farmer John 的牛棚的屋顶.门被吹飞了 好在许多牛正在度假,所以牛棚没有住满. 牛棚一个紧挨着另一个 ...

最新文章

  1. 为任务关键型Java应用优化垃圾回收
  2. buildroot--ubootkernelrootfs全编译工具
  3. MySQL—函数的使用
  4. 科目三电子路考哪些情况会被评判不合格
  5. oracle 会话 临时表,Oracle 学习系列之二(会话与事务级临时表)
  6. 基于mybatis Interceptor的对 user_cache 表 address id_no 两个字段的加密解密;
  7. 高级JAVA - 多线程之CountDownLatch
  8. LeetCode-MySQL196. 删除重复的电子邮箱
  9. Java用观察者模式重构复杂的业务代码
  10. 那年学过的web后端笔记
  11. 如何安装和使用Android夜神模拟器
  12. 职业经理人十大修炼指南 [完全版]
  13. Java基础——时间和日期
  14. Android之解析程序包时出现问题
  15. 段码超低功耗LCD液晶显示驱动芯片(IC)-VKL系列-VKL128/060/076/144A/144B,VKL144A兼容MCP144
  16. Typora入门教学
  17. phase portrait 如果爱情像数学一样
  18. STM32G431RBT6-----Timer
  19. 我们不做看客,只做时代的赋能者—FMI2018人工智能与大数据高峰论坛圆满落幕...
  20. 如何用代码实现决策树来决策要不要相亲?

热门文章

  1. 中华好诗词大学季第二季(一)
  2. 备战面试日记(4.2.13)- (框架.Spring【十三】之Spring IOC 源码finishBeanFactoryInitialization())
  3. 大脑是如何塑造你的感觉?
  4. C++ Primer 第五版 电子书(英文)pdf下载
  5. C++11之final详解
  6. Cuda与GPU显卡驱动版本一览
  7. 数据分析引擎之Kylin学习笔记
  8. Mujoco平面双足机器人模拟
  9. java名字转化为拼音_将中文姓名转换为拼音
  10. 李雅普诺夫指数 matlab,Matlab画Lorenz系统的最大李雅普诺夫指数图