Medium
题目描述
给你一个长度为 n 的整数数组 coins,表示你拥有的 n 个硬币。第 i 个硬币的价值为 coins[i]。如果你可以选择一些硬币,使得它们的价值总和为 x,那么你就可以制造出价值 x。
返回从 0 开始(包括 0)你最多能用硬币制造出多少个连续整数的价值。
注意,你可能有多个相同价值的硬币。
示例 1:
输入: coins = [1,3]
输出: 2
解释: 你可以制造出下列价值:
- 0: 取 []
- 1: 取 [1]
你可以制造出从 0 开始的 2 个连续整数价值。
示例 2:
输入: coins = [1,1,1,4]
输出: 8
解释: 你可以制造出下列价值:
- 0: 取 []
- 1: 取 [1]
- 2: 取 [1,1]
- 3: 取 [1,1,1]
- 4: 取 [4]
- 5: 取 [4,1]
- 6: 取 [4,1,1]
- 7: 取 [4,1,1,1]
你可以制造出从 0 开始的 8 个连续整数价值。
示例 3:
输入: coins = [1,4,10,3,1]
输出: 20
提示:
- coins.length == n
- 1 <= n <= 4 * 10^4
- 1 <= coins[i] <= 4 * 10^4
解题思路
这道题的关键在于理解一个贪心的性质:如果我们能够制造出 [0, x-1] 范围内的所有整数,并且有一个硬币价值为 v,那么我们就能制造出 [0, x+v-1] 范围内的所有整数。
核心思路:
- 首先将硬币按价值排序,这样可以按照从小到大的顺序处理
- 维护一个变量
reach,表示当前能够连续制造的最大值(不包括该值本身) - 对于每个硬币
coin:- 如果
coin > reach,说明存在间隙,无法继续扩展连续区间 - 否则,我们可以将连续区间扩展到
reach + coin
- 如果
算法步骤:
- 对硬币数组排序
- 初始化
reach = 1(表示我们能制造 [0, 0],即只有0) - 遍历排序后的硬币:
- 如果当前硬币值 ≤ reach,则更新
reach += coin - 否则跳出循环
- 如果当前硬币值 ≤ reach,则更新
- 返回
reach
这个算法的时间复杂度主要来自排序,为 O(n log n)。贪心策略保证了我们总是能找到最优解。
代码实现
class Solution {
public:
int getMaximumConsecutive(vector<int>& coins) {
sort(coins.begin(), coins.end());
int reach = 1; // 能够制造 [0, reach-1] 的所有值
for (int coin : coins) {
if (coin > reach) {
break; // 存在间隙,无法继续
}
reach += coin;
}
return reach;
}
};
class Solution:
def getMaximumConsecutive(self, coins: List[int]) -> int:
coins.sort()
reach = 1 # 能够制造 [0, reach-1] 的所有值
for coin in coins:
if coin > reach:
break # 存在间隙,无法继续
reach += coin
return reach
public class Solution {
public int GetMaximumConsecutive(int[] coins) {
Array.Sort(coins);
int reach = 1; // 能够制造 [0, reach-1] 的所有值
foreach (int coin in coins) {
if (coin > reach) {
break; // 存在间隙,无法继续
}
reach += coin;
}
return reach;
}
}
/**
* @param {number[]} coins
* @return {number}
*/
var getMaximumConsecutive = function(coins) {
coins.sort((a, b) => a - b);
let reach = 1; // 能够制造 [0, reach-1] 的所有值
for (let coin of coins) {
if (coin > reach) {
break; // 存在间隙,无法继续
}
reach += coin;
}
return reach;
};
复杂度分析
| 复杂度 | 大小 |
|---|---|
| 时间复杂度 | O(n log n) |
| 空间复杂度 | O(1) |
说明:
- 时间复杂度:排序需要 O(n log n),遍历数组需要 O(n),总体为 O(n log n)
- 空间复杂度:只使用了常数级别的额外空间
相关题目
- . Patching Array (Hard)