算法学习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 nums[i] 计算 dp[i] = Math.max(nums[i], dp[i-1] + nums[i]) dp[i] 结果 当前最大值 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;
    }
相关推荐
啊阿狸不会拉杆2 小时前
《计算机操作系统》第十章 - 多处理机操作系统
c++·算法·计算机组成原理·os·计算机操作系统
KmjJgWeb2 小时前
柑橘木虱目标检测与识别——基于改进YOLOv26算法的高精度检测方法研究
算法·yolo·目标检测
yongui478342 小时前
异构网络垂直切换算法MATLAB仿真实现
网络·算法·matlab
Sarvartha2 小时前
RAG学习笔记
人工智能·学习·飞书
sin_hielo2 小时前
leetcode 1200
数据结构·算法·leetcode
ZPC82102 小时前
通过神经网络识别图像位置
人工智能·算法·机器人
马猴烧酒.2 小时前
智能协图云图库学习笔记day6-主流图片优化技术
笔记·学习
时艰.2 小时前
JVM 垃圾收集器ParNew&CMS与三色标记算法
java·jvm·算法
zy_destiny2 小时前
SegEarth-OV系列(二):面向遥感图像的无训练开放词汇分割
人工智能·深度学习·算法·机器学习·计算机视觉·语义分割·开放词汇