杰瑞科技汇

ChangeCoins Python如何实现货币兑换?

Of course! The "changecoins" problem is a classic computer science challenge, often used to teach dynamic programming. It's a variation of the Coin Change Problem.

ChangeCoins Python如何实现货币兑换?-图1
(图片来源网络,侵删)

Let's break it down into three parts:

  1. Understanding the Problem
  2. The "Greedy" Approach (Why it fails)
  3. The Correct Approach: Dynamic Programming

Understanding the Problem

The goal is simple: given a set of coin denominations and a target amount, find the minimum number of coins needed to make up that amount.

Example:

  • Coins: [1, 5, 10, 25] (like US quarters, dimes, nickels, pennies)
  • Target Amount: 33
  • Solution: The minimum number of coins is 5. One way to achieve this is 25 + 5 + 1 + 1 + 1.

The problem asks for the minimum number of coins, not just any combination.

ChangeCoins Python如何实现货币兑换?-图2
(图片来源网络,侵删)

The "Greedy" Approach (Why it Fails)

The most intuitive approach is the "greedy" algorithm:

  1. Start with the largest coin.
  2. Use as many of it as possible without exceeding the target amount.
  3. Move to the next largest coin and repeat until the amount is zero.

Let's test it with our example (Amount: 33, Coins: [25, 10, 5, 1]):

  1. Largest coin is 25. Use one. Amount is now 33 - 25 = 8. Coins used: 1.
  2. Next largest is 10. Can't use it. Move to 5.
  3. Next is 5. Use one. Amount is now 8 - 5 = 3. Coins used: 2.
  4. Next is 1. Use three. Amount is now 0. Coins used: 5.

This gives us the correct answer of 5 coins. But this is a coincidence!

The Greedy Approach Fails with Different Coin Systems

ChangeCoins Python如何实现货币兑换?-图3
(图片来源网络,侵删)

Consider a different set of coins, like [1, 3, 4] and a target of 6.

  • Greedy Approach:

    1. Largest coin is 4. Use one. Amount is now 6 - 4 = 2. Coins used: 1.
    2. Next largest is 3. Can't use it. Move to 1.
    3. Use two 1's. Amount is now 0. Coins used: 3.
    • Greedy Solution: 4 + 1 + 1 (3 coins).
  • Optimal Solution:

    • 3 + 3 (2 coins).

The greedy approach fails because it makes the locally optimal choice at each step (taking the biggest coin), which doesn't lead to the globally optimal solution.


The Correct Approach: Dynamic Programming

Dynamic Programming (DP) is the standard way to solve this optimally. The core idea is to solve smaller subproblems first and use their solutions to build up the answer to the larger problem.

The Logic

Let's define an array, let's call it dp, where dp[i] will store the minimum number of coins needed to make amount i.

  1. Initialization:

    • dp[0] = 0. It takes 0 coins to make an amount of 0.
    • For all other amounts from 1 to our target, we can initialize them to a large number (like infinity or amount + 1), representing that we haven't found a way to make that amount yet.
  2. Filling the DP Table:

    • We'll iterate through every amount from 1 up to our target amount.
    • For each amount i, we'll try every single coin in our set.
    • If the coin's value is less than or equal to i, it's a candidate. We can use this coin to reduce the problem to a smaller subproblem.
    • The logic is: dp[i] = min(dp[i], dp[i - coin] + 1)
      • dp[i]: The minimum coins for amount i (what we're trying to find).
      • dp[i - coin]: The minimum coins for the smaller amount i - coin (which we have already calculated).
      • + 1: Because we are using one coin to get from i - coin to i.

Python Implementation

Here is a complete, well-commented Python function that implements this dynamic programming solution.

def changecoins(coins, amount):
    """
    Calculates the minimum number of coins needed to make up a given amount.
    Args:
        coins (list): A list of coin denominations (e.g., [1, 5, 10, 25]).
        amount (int): The target amount to make.
    Returns:
        int: The minimum number of coins needed. Returns -1 if it's not possible.
    """
    # dp[i] will be the minimum number of coins needed to make amount i.
    # Initialize dp with a value larger than any possible minimum.
    # We can use 'amount + 1' because the worst case is using 'amount' 1-coins.
    dp = [amount + 1] * (amount + 1)
    # Base case: 0 coins are needed to make amount 0.
    dp[0] = 0
    # Iterate through all amounts from 1 up to the target amount.
    for i in range(1, amount + 1):
        # For each amount, try every coin denomination.
        for coin in coins:
            # Check if the coin can be used for the current amount.
            if coin <= i:
                # The core of the DP logic:
                # The minimum coins for amount 'i' is the minimum between its current value
                # and the value of the subproblem (i - coin) plus one (for the current coin).
                dp[i] = min(dp[i], dp[i - coin] + 1)
    # After filling the dp table, check if the solution for the target amount was found.
    # If dp[amount] is still the initial large value, it means it's not possible.
    if dp[amount] > amount:
        return -1
    else:
        return dp[amount]
# --- Examples ---
# Example 1: Standard US coins
coins1 = [1, 5, 10, 25]
amount1 = 33
print(f"Coins: {coins1}, Amount: {amount1}")
print(f"Minimum coins needed: {changecoins(coins1, amount1)}")  # Expected: 5
print("-" * 20)
# Example 2: The case where the greedy algorithm fails
coins2 = [1, 3, 4]
amount2 = 6
print(f"Coins: {coins2}, Amount: {amount2}")
print(f"Minimum coins needed: {changecoins(coins2, amount2)}")  # Expected: 2 (3 + 3)
print("-" * 20)
# Example 3: An impossible case
coins3 = [2, 5, 10]
amount3 = 3
print(f"Coins: {coins3}, Amount: {amount3}")
print(f"Minimum coins needed: {changecoins(coins3, amount3)}")  # Expected: -1
print("-" * 20)
# Example 4: Simple case
coins4 = [1, 2, 5]
amount4 = 11
print(f"Coins: {coins4}, Amount: {amount4}")
print(f"Minimum coins needed: {changecoins(coins4, amount4)}")  # Expected: 3 (5 + 5 + 1)

Complexity Analysis

  • *Time Complexity: O(amount N)**

    • We have a loop that runs amount times.
    • Inside that loop, we iterate through the list of N coins.
    • Therefore, the time taken is proportional to the product of the amount and the number of coin denominations.
  • Space Complexity: O(amount)

    • We create a dp array of size amount + 1 to store our subproblem solutions. This is the primary memory usage.
分享:
扫描分享到社交APP
上一篇
下一篇