理论基础
● 455.分发饼干
● 376. 摆动序列
● 53. 最大子序和
什么是贪心
贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
这么说有点抽象,来举一个例子:
例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿?
指定每次拿最大的,最终结果就是拿走最大数额的钱。
每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。
再举一个例子如果是 有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满,如果还每次选最大的盒子,就不行了。这时候就需要动态规划。动态规划的问题在下一个系列会详细讲解
有同学问了如何验证可不可以用贪心算法呢?
最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧。
贪心一般解题步骤
贪心算法一般分为如下四步:
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
这个四步其实过于理论化了,我们平时在做贪心类的题目 很难去按照这四步去思考,真是有点“鸡肋”。
做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了
455.分发饼干
class Solution: def findContentChildren(self, g: List[int], s: List[int]) -> int: g.sort() s.sort() g_len = len(g) s_len = len(s) ans = 0 pointor1 = g_len-1 pointor2 = s_len-1 while (pointor1 >= 0 and pointor2 >= 0): if(s[pointor2] >= g[pointor1]): ans += 1 pointor1 -= 1 pointor2 -= 1 else: pointor1 -= 1 return ans
376. 摆动序列
使用三个指针
class Solution: def wiggleMaxLength(self, nums: List[int]) -> int: ans = 1 n = len(nums) pointer1 = 0 pointer2 = 1 while pointer2 < n and nums[pointer1] == nums[pointer2]: pointer1 += 1 pointer2 += 1 if pointer2 == n: return 1 ans += 1 pointer3 = pointer2 + 1 while pointer3 < n: if (nums[pointer2]-nums[pointer1])*(nums[pointer3]-nums[pointer2]) < 0: ans += 1 pointer1 = pointer2 pointer2 = pointer3 pointer3 += 1 return ans
但其实还有更简单的方法就是指记录和计算差值
如果这两个差值一正一反,就加一移动
如果同符号或者又零的存在就不移动上一个差值
53. 最大子序和
可能是负数
所以我们考虑的思路是
如果前面的和为负数
那我们就设置为当前数的大小
因为任何数字加上负数必定更小
class Solution: def maxSubArray(self, nums: List[int]) -> int: ans = nums[0] ans_now = 0 for i in nums: if ans_now <= 0: ans_now = i else: ans_now += i ans = max(ans, ans_now) return ans
标签:nums,int,pointer2,随想录,Day30,len,ans,贪心 From: https://www.cnblogs.com/fangleSea/p/17494463.html