返回

贪心算法 - LeetCode 每日刷题精华 (Day 7)

见解分享

贪心算法:优化决策,解决复杂问题

引言

在计算机科学领域,贪心算法是一种常用的方法,它通过在每一步中做出局部最优决策来解决问题,从而得到全局最优解或近似最优解。贪心算法简单易懂,实现高效,在解决许多实际问题中都有着广泛的应用。

贪心算法的原理

贪心算法的基本思想是在每次决策中选择当前看来最优的选项,而不考虑未来可能出现的更优选项。这种方法虽然不能保证得到全局最优解,但通常可以得到近似最优解,并且在时间和空间复杂度上具有优势。

LeetCode每日一题:贪心算法的实战应用

1. 分配饼干

问题:给定一数组 children 和一数组 cookies,表示 n 个孩子和 n 个饼干,每个孩子有一个胃口值,每个饼干有一个大小值。一个孩子只能吃一个饼干,饼干的大小值必须大于或等于孩子的胃口值。求最多能满足多少孩子。

贪心算法解法:

  1. 将孩子和饼干按胃口值和大小值从小到大排序。
  2. 从头开始遍历孩子和饼干数组,如果某个孩子的胃口值小于或等于某个饼干的大小值,则该孩子可以吃该饼干。
def findContentChildren(children, cookies):
    children.sort()
    cookies.sort()
    i, j = 0, 0
    cnt = 0
    while i < len(children) and j < len(cookies):
        if children[i] <= cookies[j]:
            cnt += 1
            i += 1
            j += 1
        else:
            j += 1
    return cnt

2. 不重叠区间个数

问题:给定一个区间数组 intervals,其中每个区间都有一个起始和结束时间,求不重叠区间的最大数量。

贪心算法解法:

  1. 按区间的结束时间从小到大排序。
  2. 从头开始遍历区间数组,如果当前区间的起始时间大于或等于上一个区间的结束时间,则该区间可以加入不重叠区间集合中。
def eraseOverlapIntervals(intervals):
    intervals.sort(key=lambda x: x[1])
    cnt = 0
    prev = -1e9
    for interval in intervals:
        if interval[0] >= prev:
            cnt += 1
            prev = interval[1]
    return cnt

3. 投飞镖刺破气球

问题:给定一个气球数组 balloons,其中每个气球有一个刺破气球需要的分数。求刺破所有气球的最小分数。

贪心算法解法:

  1. 按气球分数从小到大排序。
  2. 从头开始遍历气球数组,如果当前气球分数小于或等于上一个气球分数,则当前气球分数可以累加到总分数中。
def minNumberOfArrowsToBurstBalloons(balloons):
    balloons.sort(key=lambda x: x[1])
    cnt = 1
    prev = balloons[0][1]
    for balloon in balloons:
        if balloon[0] >= prev:
            cnt += 1
            prev = balloon[1]
    return cnt

4. 根据身高和序号重组队列

问题给定一个数组 people,其中每个元素是一个人的信息,包括身高和序号。求将人们按照身高从高到矮重组队列,并保证序号顺序不变。

贪心算法解法:

  1. 按身高从高到矮排序。
  2. 按序号依次将人插入重组队列中。
def reconstructQueue(people):
    people.sort(key=lambda x: (-x[0], x[1]))
    res = []
    for p in people:
        res.insert(p[1], p)
    return res

5. 买卖股票最大收益

问题:给定一个价格数组 prices,表示股票每天的价格。求买卖股票的最大收益。

贪心算法解法:

  1. 按日期遍历价格数组。
  2. 如果当前价格大于或等于上一个价格,则当前价格可以作为卖出价格。
  3. 如果当前价格小于上一个价格,则当前价格可以作为买入价格。
def maxProfit(prices):
    buy = 0
    sell = 1
    profit = 0
    while sell < len(prices):
        if prices[sell] < prices[buy]:
            buy = sell
        else:
            profit = max(profit, prices[sell] - prices[buy])
        sell += 1
    return profit

6. 买卖股票最大收益 II

问题:给定一个价格数组 prices,表示股票每天的价格。求可以进行多次买卖股票的最大收益。

贪心算法解法:

  1. 按日期遍历价格数组。
  2. 如果当前价格大于或等于上一个价格,则当前价格可以作为卖出价格。
  3. 如果当前价格小于上一个价格,则忽略当前价格。
def maxProfit(prices):
    profit = 0
    for i in range(1, len(prices)):
        if prices[i] > prices[i-1]:
            profit += prices[i] - prices[i-1]
    return profit

总结

贪心算法是一种强大的算法范式,它简单易懂,实现高效,在解决许多实际问题中都有着广泛的应用。通过以上六个 LeetCode 每日一题,我们深入理解了贪心算法的原理和解题思路。

常见问题解答

1. 贪心算法总是能得到全局最优解吗?
答:不,贪心算法不总是能得到全局最优解,它只能得到局部最优解或近似最优解。

2. 贪心算法的优势和劣势是什么?
答:贪心算法的优势是简单易懂,实现高效,适用于解决许多实际问题。劣势是它不总是能得到全局最优解,而且对于某些问题,贪心算法可能无法得到好的解。

3. 什么时候应该使用贪心算法?
答:当问题具有以下特性时,可以使用贪心算法:1) 每个决策只影响局部;2) 总是存在一个局部最优决策;3) 局部最优决策的集合可以得到全局最优解或近似最优解。

4. 贪心算法的应用有哪些?
答:贪心算法广泛应用于解决各种问题,包括调度、分配、路径规划、数据结构维护等。

5. 贪心算法与动态规划的区别是什么?
答:贪心算法只考虑当前局部最优决策,而动态规划会考虑所有可能的情况,找到最优决策。贪心算法实现简单,但不能保证全局最优解,而动态规划虽然实现复杂,但能保证全局最优解。