322. Coin Change
題目網址:https://leetcode.cn/problems/coin-change/
題意:給一整數 array
coins
, 表示不同面額的零錢, 和一整數amount
代表總金額。計算可以湊成
amount
的最少硬幣數。如果無法湊成, 則返回-1
。每種硬幣的數量都是無限的。
Solution 1:(TLE 無法通過)
想法:利用 DFS
普通版:DFS
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int res = amount + 1, count = 0;
dfs(coins, amount, count, res);
return (res == amount + 1) ? -1 : res;
}
private:
void dfs(const vector<int>& coins, const int amount, const int count, int& res){
if (amount == 0) {
res = min(count, res);
return;
} else if (amount < 0) {
return;
}
for (const auto& coin : coins) {
if (amount >= coin) {
dfs(coins, amount - coin, count + 1, res);
}
}
}
};進階版:DFS + greedy(每次取最大面額)+ pruning
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
// sort coins in descending order
sort(coins.rbegin(), coins.rend());
int res = amount + 1;
dfs(coins, 0, amount, 0, res);
return (res == amount + 1) ? -1 : res;
}
private:
void dfs(const vector<int>& coins, const int idx, const int amount, const int count, int& res) {
if (amount == 0) {
res = min(res, count);
return;
}
if (idx == coins.size()) {
return;
}
const int coin = coins[idx]; // 每次取最大面額的硬幣
for (int k = amount / coin; k >= 0 && count + k < res; --k) {
dfs(coins, idx + 1, amount - k * coin, count + k, res);
}
}
};
Solution 2:
想法:改進 Solution 1, 利用 DP 來避免重複計算(圖中綠色圈起來的部分), 其中
dp[i]
為湊齊金額i
的最少硬幣數
class Solution { |
- time:$O(amount \cdot n)$ ➔ for loop, 其中
n
為硬幣的種類 - space:$O(amount)$ ➔
dp
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Zako's Blog!
評論