返回

贪心算法的巧思:用糖果满足孩子们的饥饿度

见解分享

使用贪心算法满足饥肠辘辘的孩子

问题概述

想象一群饥肠辘辘的孩子,他们的饥饿程度各不相同,用数组 g 表示每个孩子的饥饿度,其中 g[i] 表示第 i 个孩子的饥饿度。此外,还有一袋大小各异的饼干,用数组 s 表示,其中 s[j] 表示第 j 个饼干的大小。

我们的目标是给每个孩子分配一个饼干,让每个孩子的饥饿度都能得到满足。满足的条件是:孩子的饥饿度小于或等于饼干的大小。

贪心算法

为了解决这个问题,我们采用贪心算法。贪心算法是一种经典的算法策略,它以在每一步中做出局部最优决策为原则,逐步逼近全局最优解。

贪心算法步骤

  1. 将孩子和饼干按饥饿度和大小升序排序。
  2. 遍历孩子数组 g
    • 对于每个孩子 g[i], 从左到右遍历饼干数组 s
      • 如果 g[i] <= s[j], 则给这个孩子分配 s[j] 饼干,并将 j 加 1。
  3. 遍历饼干数组 s
    • 如果还有未分配的饼干,则从右到左遍历孩子数组 g
      • 如果 g[i] >= s[j], 则给这个孩子分配 s[j] 饼干,并将 i 加 1。

算法分析

  • 时间复杂度: O(n log n),其中 n 为孩子和饼干的总数。排序的复杂度为 O(n log n),贪心分配的过程为 O(n)。
  • 空间复杂度: O(1),因为我们没有使用额外的空间。

代码实现

def findContentChildren(g, s):
    g.sort()
    s.sort()
    i, j = 0, 0
    while i < len(g) and j < len(s):
        if g[i] <= s[j]:
            i += 1
            j += 1
    return i

示例

考虑如下输入:

g = [1, 2, 3]
s = [1, 1]

贪心算法的执行过程如下:

  1. 将孩子和饼干排序:g = [1, 2, 3], s = [1, 1]
  2. 遍历孩子数组:
    • 第一个孩子 g[0] = 1 可以满足于第一个饼干 s[0] = 1,因此分配饼干给这个孩子。
    • 第二个孩子 g[1] = 2 无法满足于任何饼干,因此无法分配饼干。
    • 第三个孩子 g[2] = 3 无法满足于任何饼干,因此无法分配饼干。
  3. 遍历饼干数组:没有剩余未分配的饼干。

最终,贪心算法分配了 1 个饼干给 1 个孩子,因此函数返回 1

优点和局限

贪心算法的主要优点是简单易懂,并且在许多情况下可以提供快速的近似最优解。然而,贪心算法的一个缺点是其解不一定是全局最优解。

总结

贪心算法是解决某些优化问题的有效工具,特别是当我们希望获得快速近似解时。在给定孩子和饼干的问题中,贪心算法提供了一种简单而有效的方法来满足尽可能多的孩子的饥饿度。

常见问题解答

  1. 贪心算法是否总是找到全局最优解?

    • 不,贪心算法通常不会找到全局最优解,它只能提供一个近似解。
  2. 贪心算法何时最有效?

    • 贪心算法在局部最优决策可以导致全局最优解的情况下最有效。
  3. 贪心算法有哪些实际应用?

    • 贪心算法在作业调度、数据压缩和 Huffman 编码等领域都有广泛的应用。
  4. 如何选择最佳的贪心策略?

    • 选择最佳的贪心策略需要对具体问题进行分析和理解。
  5. 贪心算法的局限性有哪些?

    • 贪心算法可能无法保证全局最优解,并且有时可能导致错误的决策。