230811 Coin Change
【题意】: 凑零钱
【 Excepted 】:
- Time Complexity: O(sum*N)
- Auxiliary Space: O(sum)
裂开,即使已经过了 90m,但还是觉得快做出来了快做出来了。于是又挣扎了一小时。做算法题还是得定个时间,90m 内没做出来就别挣扎了,效率太低!
凑零钱有两类,一种是限制数量,另一种是不限制数量。这道题就属于不限制数量的题目。此时可以利用 DFS 的思路求解(评论区方案二)。即每一个数额都看成一个节点,并且节点是成环的,点与点之间也是双向连接。
评论区方案二 Python3 改写
【评论区方案二 - 暴力递归,超时❌ 10/1120】
py
class Solution:
def dfs(self, coins, N, sum):
if sum == 0:
return 1
if sum < 0 or N <= 0:
return 0
return self.dfs(coins, N-1, sum) + self.dfs(coins, N, sum - coins[N - 1])
def count(self, coins, N, sum):
return self.dfs(coins, N, sum)
【评论区方案二 - 记忆递归,超时❌ 90/1120】
py
class Solution:
def dfs(self, coins, N, sum, dp):
if sum == 0:
return 1
if sum < 0 or N <= 0:
return 0
if dp[N][sum] != 0:
return dp[N][sum]
dp[N][sum] = self.dfs(coins, N-1, sum, dp) + self.dfs(coins, N, sum - coins[N - 1], dp)
return dp[N][sum]
def count(self, coins, N, sum):
dp = [ [0] * (sum+1) for _ in range(N+1) ]
return self.dfs(coins, N, sum, dp)
【评论区方案二 - 循环填表✔️】
py
class Solution:
def count(self, coins, N, sum):
dp = [ [0] * (sum+1) for _ in range(N+1) ]
for i in range(N+1):
dp[i][0] = 1
for i in range(1, N+1):
for s in range(sum+1):
if s >= coins[i-1]:
dp[i][s] = dp[i-1][s] + dp[i][s - coins[i-1]]
else:
dp[i][s] = dp[i-1][s]
return dp[N][sum]
【评论区方案二 - 极致优化!✔️】
py
class Solution:
def count(self, coins, N, sum):
dp = [0] * (sum+1)
dp[0] = 1
for c in coins:
for s in range(c, sum+1):
dp[s] += dp[s-c]
return dp[sum]
评论区方案一 Python3 改写
【评论区方案一 - 暴力递归,超时❌ 10/1120】
py
class Solution:
def recursion(self, coins, idx, amount):
if idx == 0:
return 1 if amount % coins[0] == 0 else 0
notTake = self.recursion(coins, idx-1, amount)
take = 0
if coins[idx] <= amount:
take = self.recursion(coins, idx, amount-coins[idx])
return take + notTake
def count(self, coins, N, sum):
return self.recursion(coins, N-1, sum)
【评论区方案一 - 记忆递归,超时❌ 801/1120】
py
class Solution:
def recursion(self, coins, idx, amount, dp):
if idx == 0:
return 1 if amount % coins[0] == 0 else 0
if dp[idx][amount] != -1:
return dp[idx][amount]
notTake = self.recursion(coins, idx-1, amount, dp)
take = 0
if coins[idx] <= amount:
take = self.recursion(coins, idx, amount-coins[idx], dp)
dp[idx][amount] = take + notTake
return dp[idx][amount]
def count(self, coins, N, sum):
dp = [ [-1] * (sum+1) for _ in range(N) ]
return self.recursion(coins, N-1, sum, dp)
【评论区方案一 - 循环填表✔️】
py
class Solution:
def count(self, coins, N, sum):
dp = [ [0] * (sum+1) for _ in range(N) ]
for s in range(sum + 1):
if s % coins[0] == 0:
dp[0][s] = 1
for idx in range(1, N):
for s in range(sum + 1):
notTake = dp[idx - 1][s]
take = 0
if coins[idx] <= s:
take = dp[idx][s - coins[idx]]
dp[idx][s] = notTake + take
return dp[N-1][sum]
【评论区方案一 - 优化表格✔️】
py
class Solution:
def count(self, coins, N, sum):
curr = [0] * (sum + 1)
prev = [*curr]
for s in range(sum + 1):
if s % coins[0] == 0:
prev[s] = 1
for idx in range(1, N):
for s in range(sum + 1):
notTake = prev[s]
take = 0
if coins[idx] <= s:
take = curr[s - coins[idx]]
curr[s] = notTake + take
prev = [*curr]
return prev[sum]
我的方案(超时❌)
【我的 - 循环填表,超时❌ 72/1120】
py
class Solution:
def count(self, coins, N, sum):
coins.sort()
table = [ [0] * N for _ in range(sum+1) ]
for i in range(N):
table[0][i] = 1
# 很多不需要的数据,我们也把他填进去了
for s in range(1, sum+1):
for i in range(N):
# count table[s][i]
for j in range(i, N):
sum_j = s-coins[j]
if sum_j < 0:
break
table[s][i] += table[sum_j][j]
return table[sum][0]
【我的 - 记忆递归,超时❌ 60/1120】
py
class Solution:
def recursion(self, coins, N, sum, start, table):
if table[sum][start] != -1:
return table[sum][start]
if sum == 0:
table[sum][start] = 1
return 1
elif sum < 0:
table[sum][start] = 0
return 0
ans = 0
for i in range(start, N):
if sum < coins[i]:
break
ans += self.recursion(coins, N, sum-coins[i], i, table)
table[sum][start] = ans
return ans
def count(self, coins, N, Sum):
coins.sort()
table = [ [-1] * N for _ in range(Sum+1) ]
return self.recursion(coins, N, Sum, 0, table)
【我的 - 暴力递归,超时❌ 10/1120】
py
class Solution:
def recursion(self, coins, N, sum, start):
if sum == 0:
return 1
elif sum < 0:
return 0
ans = 0
for i in range(start, N):
if sum < coins[i]:
break
ans += self.recursion(coins, N, sum-coins[i], i)
return ans
def count(self, coins, N, Sum):
coins.sort()
return self.recursion(coins, N, Sum, 0)