当前位置:   article > 正文

代码随想录 day31 第八章 贪心算法 part01

代码随想录 day31 第八章 贪心算法 part01

●  理论基础

●  455.分发饼干

●  376. 摆动序列

●  53. 最大子序和

理论基础

  • 本质
    • 选择当前阶段的局部最优 —> 达到全局最优
  • 贪心的套路
    • 没有固定太路
    • 最好的策略是 举反例
      • 面试官pass:
        • 代码能跑过测试用例
        • 自己能自圆其说
  • 贪心有时候就是常识性的推导
  • 一般解题步骤
    1. 将问题分解为若干个子问题
    2. 找出适合的贪心策略
    3. 求解每一个子问题的最优解
    4. 将局部最优解堆叠成全局最优解
  • 重点:
    • 想清楚 局部最优

1. 分发饼干

关联 leetcode 455.分发饼干

  • 思路
    • 两种思路
      • 1、先满足胃口
        • 大饼干满足大胃口
          • for 倒序遍历胃口
      • 2、先满足饼干
        • 小饼干满足小胃口
          • for 正序遍历饼干
  • 题解
    • 先满足饼干

      1. func findContentChildren(g []int, s []int) int {
      2. sort.Ints(g)
      3. sort.Ints(s)
      4. child := 0//满足的孩子总数
      5. // 遍历饼干, 小满足小饼干
      6. for sIdx := 0; child < len(g) && sIdx < len(s); sIdx++ {
      7. if s[sIdx] >= g[child] {
      8. child++
      9. }
      10. }
      11. return child
      12. }
    • 先满足胃口

      1. func findContentChildren(g []int, s []int) int {
      2. sort.Ints(g)
      3. sort.Ints(s)
      4. ret := 0 //满足的孩子总数
      5. // 倒序遍历胃口, 先找到胃口大的
      6. for gIdx, sIdx := len(g)-1, len(s)-1; sIdx >= 0 && gIdx >= 0; gIdx-- {
      7. if s[sIdx] >= g[gIdx] {
      8. ret++
      9. sIdx--
      10. }
      11. }
      12. return ret
      13. }

2. 摆动序列

关联 leetcode 376. 摆动序列

  • 思路

    • 明确要求连续数字的差正负摆动
    • 从原始序列中删除元素
      • 峰值元素不能删
        • 单调坡度上的元素
          • 单调递增、单调递减的上的中间元素删除
      • 保留峰值元素
    • 局部最优:
      • 删掉单调坡上的元素
        • ==》全局最优:最长的摆动序列
    • 没必要做真实删除
      • 统计峰值的数量即可
    • 注意平坡情况
      1. 情况一:上下坡中有平坡
      2. 情况二:数组首尾两端
      3. 情况三:单调坡中有平坡
  • 题解

    1. func wiggleMaxLength(nums []int) int {
    2. if len(nums) < 2 {
    3. return len(nums)
    4. }
    5. preDiff := 0 //前一个差
    6. curDiff := 0 //后一个差
    7. res := 1 //峰值个数,默认序列最右边算一个峰值
    8. for i := 0; i < len(nums)-1; i++ {
    9. curDiff = nums[i+1] - nums[i]
    10. // 出现摆动, 统一规则都删左边的元素, 所以对 preDiff 取 零值
    11. if (curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0) {
    12. res++
    13. preDiff = curDiff
    14. }
    15. }
    16. return res
    17. }

3. 最大子序和

关联 leetcode 53. 最大子序和

  • 思路

    • 贪心解法
      • 局部最优
        • 当前 连续和 为负数的时候立刻放弃,从下一个元素重新计算 连续和
      • 全局最优
        • 选取最大的连续和
      • 取当前的 连续和当前结果值 逐步比较
  • 题解

    1. func maxSubArray(nums []int) int {
    2. res := nums[0] //最终结果
    3. count := 0 //当前连续和
    4. for i := 0; i < len(nums); i++ {
    5. count += nums[i]
    6. if count > res { //更新结果
    7. res = count
    8. }
    9. if count < 0 {//当前连续和为负数了, 重新开始计算连续和
    10. count = 0
    11. }
    12. }
    13. return res
    14. }

总结

贪心算法其实就是没有什么规律可言,所以大家了解贪心算法 就了解它没有规律的本质就够了。

不用花心思去研究其规律, 没有思路就立刻看题解。

基本贪心的题目 有两个极端,要不就是特简单,要不就是死活想不出来。

学完贪心之后再去看动态规划,就会了解贪心和动规的区别

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/504624
推荐阅读
相关标签
  

闽ICP备14008679号