算法学习day27-贪心算法

概念

什么是贪心算法?

贪心的本质 是选择每一阶段的局部最优解, 从而达到全局最优

分饼干

核心思路

找出每一阶段的局部最优解, 这道题中, 有两种局部最优解, 都从最小的开始, 最小的饼干喂给胃口最小的孩子. 要么最大的饼干喂给最大胃口的孩子

  • 题解 最大喂最大

    java 复制代码
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int i = g.length - 1;
        int j = s.length - 1;
        int count = 0;
        while (i >= 0 && j >= 0) {
            if (g[i] <= s[j]) {
                count++;
                i--;
                j--;
            } else {
                i--;
            }
        }
        return count;
    }
  • 最小喂最小

    java 复制代码
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int i = 0;
        int j = 0;
        int count = 0;
        while (i < g.length && j < s.length) {
            if (g[i] <= s[j]) {
                count++;
                i++;
            }
            j++;
        }
        return count;
    }

摆动序列

核心思路

  • 可以将这个算法题, 理解为每一小段序列中, 找到波峰和波谷
  • 如果是平峰, 那么如果平峰前面的preDiff>0, 那么就相当于上一个节点是波峰, 下一个curDiff必须<0才行. 所以 preDiff >= 0 and curDiff < 0
  • 如果平峰前面的preDiff < 0, 那就相当于上一个节点是波谷, 下一个curDiff必须>0才行. 所以 preDiff <= 0 and curDiff > 0

题解

  • 普通贪心算法思路

    java 复制代码
    public int wiggleMaxLength(int[] nums) {
        if (nums.length <= 1) {
            return nums.length;
        }
        if (nums.length == 2) {
            return nums[0] != nums[1] ? 2 : 1;
        }
        int preDiff = nums[1] - nums[0];
        int count = 2;
        for (int i = 2; i < nums.length; i++) {
            int diff = nums[i] - nums[i - 1];
            if (diff > 0 && preDiff <= 0 || diff < 0 && preDiff >= 0) {
                count++;
                preDiff = diff;
            }
        }
        return count;
    }
  • 动态规划思路(第一次接触, 有点难理解, 借助ai才勉强理解了, 等后面复习吧)

    java 复制代码
    public int wiggleMaxLength1(int[] nums) {
        if (nums.length <= 1) {
            return nums.length;
        }
        // dp[i][0] 表示 截止到i 的序列, i作为波峰最长摆动序列的长度, dp[i][1] 表示 截止到i 的序列, i作为波谷最长摆动序列的长度
        int[][] dp = new int[nums.length][2];
        dp[0][0] = dp[0][1] = 1;
        for (int i = 1; i < nums.length; i++) {
            dp[i][0] = dp[i][1] = 1;
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    // i 是 波峰, j是波谷, 那么i作为波峰的最大摇摆序列长度, = j的波谷最大摇摆序列长度 + 1
                    dp[i][0] = Math.max(dp[i][0], dp[j][1] + 1);
                }
                if (nums[i] < nums[j]) {
                    // i 是 波谷, j是波峰, 那么i作为波谷的最大摇摆序列长度, = j的波峰最大摇摆序列长度 + 1
                    dp[i][1] = Math.max(dp[i][1], dp[j][0] + 1);
                }
            }
        }
        return Math.max(dp[nums.length - 1][0], dp[nums.length - 1][1]);
    }

最大子序和

核心思路

  • 这道题贪心的点在与, 如果sum < 0, 那么再+=sum只会变小, 所以直接舍弃sum, sum=当前值, 重新计数

    java 复制代码
    public int maxSubArray(int[] nums) {
        int sum = nums[0];
        int max = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (sum > 0) {
                sum = sum + nums[i];
            } else {
                sum = nums[i];
            }
            max = Math.max(sum, max);
        }
        return max;
    }
  • 动态规划

    • 以下是输入 nums = -2, 1, -3, 4, -1, 2, 1, -5, 4 的具体计算过程:

      步骤分解
    索引 i numsi 计算 dpi = Math.max(numsi, dpi-1 + numsi) dpi 结果 当前最大值 max 解释
    0 -2 (初始赋值) -2 -2 以 -2 结尾,只能是 -2
    1 1 max(1, -2 + 1) 1 1 1 比 -1 大,决定"自立门户"
    2 -3 max(-3, 1 + (-3)) -2 1 -2 比 -3 大,选择"加入队伍"
    3 4 max(4, -2 + 4) 4 4 4 比 2 大,决定"自立门户"
    4 -1 max(-1, 4 + (-1)) 3 4 3 比 -1 大,选择"加入队伍"
    5 2 max(2, 3 + 2) 5 5 5 比 2 大,选择"加入队伍"
    6 1 max(1, 5 + 1) 6 6 6 比 1 大,选择"加入队伍"
    7 -5 max(-5, 6 + (-5)) 1 6 1 比 -5 大,选择"加入队伍"
    8 4 max(4, 1 + 4) 5 6 5 比 4 大,选择"加入队伍"
    java 复制代码
    public int maxSubArray(int[] nums) {
        // dp[i] 表示以i为结尾的子数组的最大和
        int[] dp = new int[nums.length];
        int max = nums[0];
        dp[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
            dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);
            max = Math.max(max, dp[i]);
        }
        return max;
    }
相关推荐
雪碧聊技术7 小时前
力扣 LCR 091. 粉刷房子 —— 动态规划入门详解
算法·动态规划
遇乐的果园9 小时前
前端学习笔记-vue加载渲染优化
前端·笔记·学习
CV-Climber9 小时前
检索技术的实际应用
人工智能·算法
hhzz10 小时前
Tiger AI Platform平台中增加人脸识别功能
图像处理·人工智能·算法·计算机视觉·大模型
遇乐的果园10 小时前
前端学习笔记-vue状态管理优化
前端·笔记·学习
从零开始的代码生活_11 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法
可乐奶茶sky11 小时前
AI Agent 学习
人工智能·学习
TsingtaoAI11 小时前
3D高斯泼溅技术发展及其在具身智能领域的应用综述
人工智能·算法·ai·具身智能·高斯泼溅
atunet11 小时前
关于图算法中的连通分量检测与最小割问题7
算法