贪心算法01 | ● 理论基础 ● 455.分发饼干 ● *376. 摆动序列 ● *53. 最大子序和

理论基础

https://programmercarl.com/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

  • 贪心算法总括
  • 贪心算法的本质:由局部最优推到全局最优
  • 贪心算法的套路:无固定套路

455.分发饼干

https://programmercarl.com/0455.%E5%88%86%E5%8F%91%E9%A5%BC%E5%B9%B2.html

  • 考点
    • 贪心算法
  • 我的思路
    • 将胃口和饼干数组排序
    • 大胃口给大饼干
    • 两层for循环,一层遍历胃口,一层遍历饼干
  • 视频讲解关键点总结
    • 无视频
    • 文字讲解的重点在于降低算法的时间复杂度
      • 把饼干的那重循环利用if判断替换
  • 我的思路的问题
    • 时间复杂度高
  • 代码书写问题
  • 可执行代码
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()
        s.sort()
        index = len(s) - 1
        result = 0
        for i in range(len(g) - 1, -1, -1):
            if index >= 0 and s[index] >= g[i]:
                result += 1
                index -= 1
        return result

*376. 摆动序列

https://programmercarl.com/0376.%E6%91%86%E5%8A%A8%E5%BA%8F%E5%88%97.html

  • 考点
    • 贪心算法(二刷用的动态规划,比较好理解也好写)
  • 我的思路
    • 无思路
  • 视频讲解关键点总结
    • 二刷用的动规,因此这里先写动规的思路:
      • dp数组的含义是,到当前元素i的位置时,对应的最长摆动序列是多长;其中每个i对应2个状态,状态0是当前元素i扮演山峰的角色(值比序列中的前后元素大),状态1是当前元素扮演山谷的角色(值比序列中的前后元素小)
      • 递推公式,当前元素i的dp值应遍历从头开始到i的每个元素j,并比较其与i的大小来进行更新,如果j比i大,则i扮演山谷角色,此时dp[i][1] = max(dp[i][1], dp[j][0] + 1);j比i小,i扮演山峰角色,此时dp[i][0] = max(dp[i][0], dp[j][1] + 1)
      • 初始化,由于题目中说了只有一个元素也算摆动序列,所以dp值最小为1,因此初始化为1
      • 循环遍历,双层,外层遍历i,内层遍历j
    • 以下为贪心的思路:
    • 关键点1:只需要遇到摆动点记录一次长度即可,不需要更改原序列
    • 关键点2:除了前后差值异号的情况,还有前差值为0、后差值存在的情况
      • 对于前差值为0的情况,又分为单调递增中包含平台的情况和摆动中包含平台的情况
      • 情况解析
    • 关键点3:头尾元素也被记录为一次摆动
  • 我的思路的问题
    • 无思路
  • 代码书写问题
  • 可执行代码
# 动态规划思路代码
class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        dp = [[1] * 2 for _ in range(len(nums))]
        for i in range(len(nums)):
            for j in range(i):
                if nums[j] < nums[i]:
                    dp[i][0] = max(dp[i][0], dp[j][1] + 1)
                elif nums[j] > nums[i]:
                    dp[i][1] = max(dp[i][1], dp[j][0] + 1)
        return max(dp[-1][0], dp[-1][1])
# 贪心思路代码
class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        pre_diff = 0
        cur_diff = 0
        result = 1
        for i in range(len(nums) - 1):
            cur_diff = nums[i + 1] - nums[i]
            if (pre_diff <= 0 < cur_diff) or (pre_diff >= 0 > cur_diff):
                result += 1
                pre_diff = cur_diff
        return result

*53. 最大子序和

https://programmercarl.com/0053.%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C.html

  • 考点
    • 贪心算法
  • 我的思路
    • 无思路
  • 视频讲解关键点总结
    • 暴力解法
      • 双层for循环,计算所有连续子序列的和,然后找最大值
    • 贪心解法
      • 如果当前和值为负数,则一定对后续和有削减作用,因此一到和值为复数,就将当前累加和归为0,重新开始
      • 在过程中记录最大值
  • 我的思路的问题
    • 无思路
  • 代码书写问题
    • 可以用float('-inf')取极小值
  • 可执行代码
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        summ = 0
        max_num = float('-inf')
        for i in range(len(nums)):
            summ += nums[i]
            if summ > max_num:
                max_num = summ
            if summ < 0:
                summ = 0
        return max_num
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值