需要添加的硬币的最小数量
难度:
标签:
题目描述
You are given a 0-indexed integer array coins
, representing the values of the coins available, and an integer target
.
An integer x
is obtainable if there exists a subsequence of coins
that sums to x
.
Return the minimum number of coins of any value that need to be added to the array so that every integer in the range [1, target]
is obtainable.
A subsequence of an array is a new non-empty array that is formed from the original array by deleting some (possibly none) of the elements without disturbing the relative positions of the remaining elements.
Example 1:
Input: coins = [1,4,10], target = 19 Output: 2 Explanation: We need to add coins 2 and 8. The resulting array will be [1,2,4,8,10]. It can be shown that all integers from 1 to 19 are obtainable from the resulting array, and that 2 is the minimum number of coins that need to be added to the array.
Example 2:
Input: coins = [1,4,10,5,7,19], target = 19 Output: 1 Explanation: We only need to add the coin 2. The resulting array will be [1,2,4,5,7,10,19]. It can be shown that all integers from 1 to 19 are obtainable from the resulting array, and that 1 is the minimum number of coins that need to be added to the array.
Example 3:
Input: coins = [1,1,1], target = 20 Output: 3 Explanation: We need to add coins 4, 8, and 16. The resulting array will be [1,1,1,4,8,16]. It can be shown that all integers from 1 to 20 are obtainable from the resulting array, and that 3 is the minimum number of coins that need to be added to the array.
Constraints:
1 <= target <= 105
1 <= coins.length <= 105
1 <= coins[i] <= target
代码结果
运行时间: 92 ms, 内存: 26.4 MB
/*
* Problem statement: Same as above.
*
* Solution approach using Java Streams:
* 1. Sort the coins using streams.
* 2. Iterate over the sorted list to calculate the smallest missing sum and required additions.
* 3. Return the number of coins added.
*/
import java.util.Arrays;
public class MinCoinsStream {
public static int minAdditions(int[] coins, int target) {
// Sort the array using streams
coins = Arrays.stream(coins).sorted().toArray();
long missingSum = 1; // Start with the smallest missing value
int addedCoins = 0; // Number of coins added
for (int coin : coins) {
if (missingSum > target) break;
if (coin <= missingSum) {
missingSum += coin;
} else {
while (missingSum < coin && missingSum <= target) {
missingSum += missingSum;
addedCoins++;
}
missingSum += coin;
}
}
while (missingSum <= target) {
missingSum += missingSum;
addedCoins++;
}
return addedCoins;
}
public static void main(String[] args) {
int[] coins = {1, 4, 10};
int target = 19;
System.out.println(minAdditions(coins, target)); // Output: 2
}
}
解释
方法:
该题解使用了贪心算法来确定最少需要添加的硬币数量以覆盖从1到target的所有金额。首先对硬币进行排序,然后用两个指标来跟踪:right表示当前可以通过已有硬币和新加入的硬币连续覆盖的最大值,i是遍历硬币数组的索引。在每次迭代中,如果当前硬币值大于right+1(表示有缺口无法用现有的硬币连续覆盖到该硬币的值),则添加一个硬币,其面值为right+1,以此填补缺口并尝试增大覆盖范围。这样保持覆盖范围的连续性,直到覆盖到target。最后,返回添加的硬币数量。
时间复杂度:
O(n log n)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在遍历硬币值时,如果遇到当前硬币值大于right+1,你选择添加面值为right+1的硬币而不是其他值?
▷🦆
在该算法中,当所有给定的硬币都已使用完毕,而right仍未达到target时,你是如何确定接下来需要添加的硬币数和面值的?
▷🦆
该贪心策略是否保证了最小数量的硬币添加?存在哪些情况可能导致需要添加的硬币数目不是最优解?
▷🦆
在执行while循环时,对于right每次增加right + 1的策略为何能有效覆盖到target,这里的数学原理是什么?
▷