前端算法·专项攻破十:贪心算法

1,133 阅读3分钟

概念理解

贪心算法(英语:greedy algorithm),又称贪婪算法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。-- 维基百科

贪心算法是算法设计中的一种方法。期盼通过每个阶段的局部最优选择,从而达到全局最优,但是结果并不一定是最优的。常见的反面例子如:零钱兑换问题。

使用场景

二叉树等算法题,解题经常用到贪心算法。

详细可参考以下例题讲解,通过刷以下题集以加深和巩固对于模拟算法的理解。

例题讲解

题目: 分糖果问题

描述

一群孩子做游戏,现在请你根据游戏得分来发糖果,要求如下:

  1. 每个孩子不管得分多少,起码分到一个糖果。
  2. 任意两个相邻的孩子之间,得分较多的孩子必须拿多一些糖果。(若相同则无此限制) 给定一个数组 arr 代表得分数组,请返回最少需要多少糖果。

要求: 时间复杂度为 O(n),空间复杂度为 O(n)

示例1

输入:

[1, 1, 2]

返回值:

4

说明:

最优分配方案为 1, 1, 2 

示例2

输入:

[1, 1, 1]

返回值:

3

说明:

最优分配方案是 1, 1, 1 

题解:

/**
 * 解法:贪心
 * 思路:
 *   要想分出最少的糖果,利用贪心思想,肯定是相邻位置没有增加的情况下大家都分到1, 
 *   相邻位置有增加的情况下,分到糖果数加1就好。什么情况下会增加糖果,相邻位置有得
 *   分差异,可能是递增可能是递减,如果是递增的话,糖果依次加1,如果是递减糖果依次减1?
 *   这不符合最小,必须从1开始加才是最小,那我们可以反向加1.
 * 时间复杂度:O(n),单独遍历两次.
 * 空间复杂度:O(n)。记录每个位置糖果数的辅助数组.
 */
export function candy(arr: number[]): number {
    const len = arr.length
    if (len <= 1) return len
    let nums: number[] = []
    for (let i = 0; i < len; i++) {
        nums[i] = 1
    }
    for (let i = 1; i < len; i++) {
        if (arr[i] > arr[i - 1]) { // 如果右边在递增,每次增加一个
            nums[i] = nums[i - 1] + 1
        }
    }

    let res = nums[len - 1] // 记录总糖果数
    for (let i = len - 2; i >= 0; i--) {
        if (arr[i] > arr[i + 1] && nums[i] <= nums[i + 1]) { // 如果左边更大但是糖果树更小
            nums[i] = nums[i + 1] + 1
        }
        res += nums[i] // 累加和
    }

    return res
}

题集&题解

序号题目题解难度
1分糖果问题题解medium
2主持人调度(二)题解medium

相关文章

您的点赞和评论是我持续更新的动力,感谢关注。