算法学习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;
    }
相关推荐
汉克老师5 分钟前
GESP2025年3月认证C++五级( 第三部分编程题(2、原根判断))
c++·算法·模运算·gesp5级·gesp五级·原根·分解质因数
Amazing_Cacao7 分钟前
CFCA精品可可产区认证课程风土解析(美洲):打破风味堆叠的假象,建立时间轴上的层次展开阅读系统
学习
永远不会的CC20 分钟前
浙江华昱欣实习(4月23日~ 4月19日)
后端·学习
数据皮皮侠27 分钟前
上市公司创新韧性数据(2000-2024)|顶刊同款 EIR 指数
大数据·人工智能·算法·智慧城市·制造
爱上好庆祝28 分钟前
学习js的第五天
前端·css·学习·html·css3·js
WL_Aurora30 分钟前
Python 算法基础篇之链表
python·算法·链表
科研前沿38 分钟前
纯视觉无感解算 + 动态数字孪生:室内外无感定位技术全新升级
大数据·人工智能·算法·重构·空间计算
qiaozhangchi39 分钟前
求解器学习笔记
笔记·python·学习
Wadli1 小时前
26.单调栈
算法
bendandawugui1 小时前
PCIe协议学习-PCIe的No Snoop Attr使用
学习