算法学习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;
    }
相关推荐
历程里程碑11 分钟前
Linux22 文件系统
linux·运维·c语言·开发语言·数据结构·c++·算法
你撅嘴真丑7 小时前
第九章-数字三角形
算法
uesowys8 小时前
Apache Spark算法开发指导-One-vs-Rest classifier
人工智能·算法·spark
ValhallaCoder8 小时前
hot100-二叉树I
数据结构·python·算法·二叉树
执笔论英雄8 小时前
【大模型学习cuda】入们第一个例子-向量和
学习
董董灿是个攻城狮8 小时前
AI 视觉连载1:像素
算法
wdfk_prog8 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
智驱力人工智能8 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
孞㐑¥9 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
月挽清风9 小时前
代码随想录第十五天
数据结构·算法·leetcode