简体   繁体   English

我怎样才能提高它的运行时间

[英]How can I improve its runtime

Problem Statement: You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.问题陈述:给定一个表示不同面额硬币的整数数组硬币和一个表示总金额的整数数量。 Return the fewest number of coins that you need to make up that amount.返回您需要的最少数量的硬币来弥补该金额。 If that amount of money cannot be made up by any combination of the coins, return -1.如果该金额不能由任何硬币组合弥补,则返回-1。 You may assume that you have an infinite number of each kind of coin.您可以假设您拥有无限数量的每种硬币。

Is there a way to make my solution faster?有没有办法让我的解决方案更快?
Explanation: dp[curr_amount] stores the minimum number of how many more coins I would need to reach target amount说明: dp[curr_amount] 存储我需要多少硬币才能达到目标金额的最小数量

def coinChange(self, coins: List[int], amount: int) -> int:
        
        if amount == 0:
            return 0
        
        dp = {}                
        def backtrack(curr_amount):            
            if (curr_amount) in dp:
                return dp[curr_amount]
            
            if curr_amount == amount:
                return 0
            
            if curr_amount > amount:
                return inf
                
            
            for coin in coins:
                if (curr_amount) not in dp:
                    dp[curr_amount] = inf
                # Take the minimum number of coins needed given all the possible choices
                dp[curr_amount] = min(dp[curr_amount], 1 + backtrack(curr_amount + coin))
                    
            return dp[curr_amount]
        
        res = backtrack(0)
        
        if res == inf:
            return -1
        
        return res

Not sure how to fix your way, but can try to see if this can speed up.不确定如何fix您的问题,但可以尝试看看这是否可以加快速度。 It's DP bottom-up approach:这是 DP 自下而上的方法:

It's kind of follow @joanis thought (inspired by).这有点像@joanis 的想法(灵感来自)。 Thanks.谢谢。

def min_coin_change(target, coins):
    # bottom up approach
    
    dp = [float("inf") for _ in range(target+1)]
    
    dp[0] = 0
    
    for i in range(1, target+1):
        for coin in coins:
            if i >= coin:
                dp[i] = min(dp[i], 1 + dp[i-coin])
    return dp[target] if dp[target] != float("inf") else -1



if __name__ == '__main__':
    coins = [1, 2, 5, 10]
    target = 17

    print(min_coin_change(target, coins))  # 3

    print(min_coin_change(24, coins))      # 4
    print(min_coin_change(124, coins))      # 14

I would suggest the breadth-first search approach.我建议使用广度优先搜索方法。

The idea is as follows:思路如下:

  1. Any value c in coins can be reached in one step coins中的任何值c都可以一步达到
  2. If we can reach a value x in s steps, then we can reach x+c in s+1 steps, for each c in coins.如果我们可以在s步内达到值x ,那么我们可以在s+1步内达到x+c ,对于每个c硬币。

So, we can expand the mapping from the target to the minimum steps efficiently by using the queue structure.因此,我们可以通过使用队列结构有效地将映射从目标扩展到最小步骤。

from collections import deque

def coinChange(coins: list, target: int):
  # breadth-first search using queue data structure
  v = {0: 0}
  q = deque([0])
  while len(q) > 0:
    cur = q.popleft()
    for coin in coins:
      nxt = cur + coin  # we can reach this value in one more step
      if nxt in v:  # we have already covered this amount in shorter step
        continue
      if nxt == target:  # we have reached the target
        return v[cur] + 1 
      if nxt < target:
        # we continue the search only for the values smaller than the target
        # because the value is only increasing
        v[nxt] = v[cur] + 1
        q.append(nxt)
  # we could not reach the target value
  return -1

print(coinChange([1, 2, 5, 10], 17))  # 3
print(coinChange([1, 2, 5, 10], 24))  # 4
print(coinChange([1, 2, 5, 10], 124)) # 14
print(coinChange([5, 8], 12))         # -1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM