【面试高频算法解析】算法练习7 贪心算法

2024-01-08 12:51:13

前言

本专栏旨在通过分类学习算法,使您能够牢固掌握不同算法的理论要点。通过策略性地练习精选的经典题目,帮助您深度理解每种算法,避免出现刷了很多算法题,还是一知半解的状态


专栏导航

  1. 二分查找
  2. 回溯(Backtracking)
  3. 双指针
  4. 滑动窗口
  5. 深度优先搜索
  6. 广度优先搜索
  7. 贪心算法
  8. 单调队列
  9. 堆(Heap)

算法解析

贪心算法(Greedy Algorithm)是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法策略。

贪心算法在有最优子结构的问题中尤其有效,这种子结构意味着局部最优解能决定全局最优解。简单地说,一个问题的最优解包含其子问题的最优解。贪心算法不一定能求得所有问题的全局最优解,因为它通常没有考虑前面的选择如何影响后面的选择(即它不回溯)。但在很多情况下,贪心算法可以产生最优解或接近最优的解。

贪心算法的步骤通常如下:

  1. 建立数学模型:将问题抽象为数学模型。

  2. 定义选择过程:明确每一步如何选择最优解。

  3. 证明局部最优能导致全局最优:这是使用贪心算法的关键,需要证明每一步的局部最优解能最终合成全局最优解。

  4. 构建算法:根据定义的模型和选择过程来实现算法。

  5. 求解并验证:运行算法求解,然后验证算法的正确性和效率。

贪心算法常用于解决优化问题,例如:

  • 找零问题:如何用最少的硬币找零。
  • 最小生成树:如Prim算法和Kruskal算法。
  • 任务调度问题:如何安排工作以最小化等待时间或延迟。
  • 图的最短路径问题:如Dijkstra算法。

以下是一个简单的贪心算法示例,解决找零问题:

def coin_change(coins, amount):
    coins.sort(reverse=True)  # 将硬币从大到小排序
    num_coins = 0
    for coin in coins:
        if amount <= 0:
            break
        num_coins += amount // coin
        amount %= coin
    return num_coins if amount == 0 else -1  # 如果无法正好找零,返回-1

# 示例
coins = [25, 10, 5, 1]
amount = 63
print(coin_change(coins, amount))  # 输出应该是找零所需的最少硬币数

在这个例子中,算法从最大的硬币开始,尽可能多地使用大硬币,然后逐渐使用更小的硬币,直到找零完成。这个特定问题的贪心策略能够得到最优解,因为硬币的面额都是彼此的倍数。然而对于不是倍数关系的面额,贪心策略可能就无法得到最优解了。因此,使用贪心算法时,需要根据问题的具体情况来判断其适用性。


实战练习

最长回文串

给定一个包含大写字母和小写字母的字符串 s ,返回 通过这些字母构造成的 最长的回文串 。

在构造过程中,请注意 区分大小写 。比如 “Aa” 不能当做一个回文字符串。

示例 1:
输入:s = “abccccdd”
输出:7
解释: 我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

示例 2:
输入:s = “a”
输出:1

示例 3:
输入:s = “aaaaaccc”
输出:7

提示:
1 <= s.length <= 2000
s 只由小写 和/或 大写英文字母组成

官方题解


跳跃游戏II

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i]
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。

示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

示例 2:
输入: nums = [2,3,0,1,4]
输出: 2

提示:
1 <= nums.length <= 104
0 <= nums[i] <= 1000
题目保证可以到达 nums[n-1]

官方题解


买卖股票的最佳时机II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

示例 1:
输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
总利润为 4 + 3 = 7 。

示例 2:
输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
总利润为 4 。

示例 3:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。

提示:
1 <= prices.length <= 3 * 104
0 <= prices[i] <= 104

官方题解

文章来源:https://blog.csdn.net/sinat_41883985/article/details/135346962
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。