硬币找零问题被许多人认为是理解称为动态规划的编程范式的必不可少的。两者经常总是配对在一起,因为硬币找零问题包含了动态编程的概念。对于那些不了解动态编程的人来说,它是根据Wikipedia提供的,
“both a mathematical optimization method and a computer programming method … it refers to simplifying a complicated problem by breaking it down into simpler sub-problems”.
换句话说,动态问题是一种编程方法,用于将问题简化为较小的部分。例如,如果仅询问您什么是3 * 89?您可能不知道答案,因为您可能知道2 *2。但是,如果您知道3 * 88(264),那么肯定可以推论3 *89。您所要做的就是在前面的倍数上加3,您将得出267的答案。因此,这是对什么是动态编程的非常简单的解释,也许您现在可以看到如何将其有效地用于解决大型时间复杂性问题。
通过牢记上述对动态编程的定义,我们现在可以继续进行“硬币更改问题” 。以下是硬币找零问题的众多变体之一的示例。给定一个硬币列表,即1美分,5美分和10美分,您能确定给定列表中的硬币组合总数以组成数字N吗?
示例1 :假设您给硬币1分,5分和10分,而N = 8分,那么您可以安排获得8分的硬币的总数是多少。
Input: N=8
Coins : 1, 5, 10
Output: 2
Explanation:
1 way:
1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 8 cents.
2 way:
1 + 1 + 1 + 5 = 8 cents.
您要做的就是确定所有8美分面额的方式。八个1分钱加起来等于8分钱。三1分加一5分便是8分。因此,共有两种方式给出了硬币1、5和10的列表,以获得8美分。
示例2 :假设您给硬币1分,5分和10分,而N = 10分,那么您可以安排获得10分的硬币的总数是多少。
Input : N=10
Coins : 1, 5, 10
Output : 4
Explanation:
1 way:
1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 10 cents.
2 way:
1 + 1 + 1 + 1 + 1 + 5 = 10 cents.
3 way:
5 + 5 = 10 cents.
4 way:
10 cents = 10 cents.
现在我们知道了问题陈述以及如何找到较小值的解决方案,我们如何确定增加较大值的硬币组合的总数?我们写一个程序。我们如何编写程序来计算获得N较大值的所有方法?很简单,我们使用动态编程。请记住,动态编程背后的想法是将问题的每个部分切成小块。与页面顶部的示例相似。如果我们不知道4 * 36的值,但是知道4 * 35的值(140),我们可以将这个值加4并得到4 * 36的答案,顺便说一下是144。
好的,所以我们了解了我们必须做的事情,但是程序将如何确定硬币列表可以输出N种方式呢?好吧,让我们看一下这个例子。
N = 12
Index of Array: [0, 1, 2]
Array of coins: [1, 5, 10]
这是一堆硬币,分别是1美分,5美分和10美分。 N是12美分。因此,我们需要想出一种可以使用这些硬币价值并确定我们赚取12美分的方法的方法。
动态思考,我们需要弄清楚如何添加到以前的数据。因此,这意味着我们必须添加到以前的解决方案中,而不是对相同的值进行重新计算。显然,我们必须遍历整个硬币阵列。我们还需要一种方法来查看硬币是否大于N值。
一种实现方法是让一个数组一直计数到第N个值。
所以 …
多种方法:
[0, 0, 0 ..... Nth value] in our case it would be up to 12.
之所以要使用第N个值的数组,是因为这样,我们就可以确定硬币在方式数组的索引处构成值的方式数量。我们这样做是因为,如果我们可以确定某个硬币大于该索引处的值,那么显然我们不能使用该硬币来确定硬币的组合,因为该硬币大于该值。通过示例可以更好地理解这一点。
以上述数字为例。
N = 12
Index of Array of Coins:
[0, 1, 2]
Array of coins:
[1, 5, 10]
Index of Array of ways:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Array of ways:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
在开始迭代之前,我们必须为Ways数组提供一个预定义的值。我们必须将Ways数组的索引0处的第一个元素设置为1。这是因为有1种方法可以使用0个硬币使数字0。
因此,如果我们开始遍历所有coins数组并将这些元素与Ways数组进行比较,我们将确定硬币可以使用多少次来制作Ways数组的索引处的值。
例如…
首先设置方式[0] = 1。
让我们比较一下第一枚硬币,即1美分。
N = 12
Index of Array of Coins:
[0, 1, 2]
Array of coins:
[1, 5, 10]
Index of Array of ways:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Array of ways:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Then compare coins[0] to all of the index's
of ways array. If the value of the coin is less
than or equal to the ways index, then
ways[j-coins[i]]+ways[j] is the new value of
ways[j]. We do this because we are
trying to break each part down into smaller
pieces. You will see what is happening as
you continue to read. So comparing each value of the
ways index to the first coin, we get the following.
Index of Array of ways:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Array of ways:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
现在比较第二枚硬币5美分。
N = 12
Index of Array of Coins:
[0, 1, 2]
Array of coins:
[1, 5, 10]
Index of Array of ways:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Array of ways:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Comparing 5 cents to each of the index and
making that same comparison, if the value
of the coin is smaller than the value of
the index at the ways array then ways[j-coins[i]]+ways[j]
is the new value of ways[j]. Thus we
get the following.
Index of Array of ways:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Array of ways:
[1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3]
We are determining how many times the second
coin goes into all of the values leading up the
Nth coin. Why are we using all
of the coins? It is to check our previous
result dynamically and update our answer
instead of recalculating all over again.
For example take the element at index 10
the answer is 3 so far. But how did we get 3?
We know that the value of 10-5 is 5 so that
is our j-coins[i] value, that is the
difference of what needs to be made up to
make the amount 10. So we look at index 5 of the
ways array and see it has the value 2, for
the same reason as above, there are so far 2
ways to obtain the value 5. So if there are
2 ways to obtain the value 5 then those ways
plus the current number of ways is the new
updated value of the TOTAL
ways to get the value at index 10.
现在让我们比较一下第三枚硬币,即10美分。
N = 12
Index of Array of Coins:
[0, 1, 2]
Array of coins:
[1, 5, 10]
Comparing 10 cents to each of the index
and making that same comparison, if the
value of the coin is smaller than the value of the
index at the ways array then
ways[j-coins[i]]+ways[j] is the new value of ways[j].
Thus we get the following.
Index of Array of ways:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Array of ways:
[1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 4, 4, 4]
So the answer to our example is ways[12] which is 4.
考虑到以上所有内容,让我们看下面的以下程序。
C++
#include
using namespace std;
/* We have input values of N and an array Coins
that holds all of the coins. We use data type
of long because we want to be able to test
large values
without integer overflow*/
long getNumberOfWays(long N, vector Coins)
{
// Create the ways array to 1 plus the amount
// to stop overflow
vector ways(N + 1);
// Set the first way to 1 because its 0 and
// there is 1 way to make 0 with 0 coins
ways[0] = 1;
// Go through all of the coins
for(int i = 0; i < Coins.size(); i++)
{
// Make a comparison to each index value
// of ways with the coin value.
for(int j = 0; j < ways.size(); j++)
{
if (Coins[i] <= j)
{
// Update the ways array
ways[j] += ways[(j - Coins[i])];
}
}
}
// Return the value at the Nth position
// of the ways array.
return ways[N];
}
void printArray(vector coins)
{
for(long i : coins)
cout << i << "\n";
}
// Driver Code
int main()
{
vector Coins = { 1, 5, 10 };
cout << "The Coins Array:" << endl;
printArray(Coins);
cout << "Solution:" << endl;
cout << getNumberOfWays(12, Coins) << endl;
}
// This code is contributed by mohit kumar 29
Java
/* We have input values of N and an array Coins
that holds all of the coins. We use data type
of long because we want to be able to test
large values
without integer overflow*/
class getWays {
static long getNumberOfWays(long N, long[] Coins)
{
// Create the ways array to 1 plus the amount
// to stop overflow
long[] ways = new long[(int)N + 1];
// Set the first way to 1 because its 0 and
// there is 1 way to make 0 with 0 coins
ways[0] = 1;
// Go through all of the coins
for (int i = 0; i < Coins.length; i++) {
// Make a comparison to each index value
// of ways with the coin value.
for (int j = 0; j < ways.length; j++) {
if (Coins[i] <= j) {
// Update the ways array
ways[j] += ways[(int)(j - Coins[i])];
}
}
}
// return the value at the Nth position
// of the ways array.
return ways[(int)N];
}
static void printArray(long[] coins)
{
for (long i : coins)
System.out.println(i);
}
public static void main(String args[])
{
long Coins[] = { 1, 5, 10 };
System.out.println("The Coins Array:");
printArray(Coins);
System.out.println("Solution:");
System.out.println(getNumberOfWays(12, Coins));
}
}
Python3
''' We have input values of N and an array Coins
that holds all of the coins. We use data type
of because long we want to be able to test
large values
without integer overflow'''
def getNumberOfWays(N, Coins):
# Create the ways array to 1 plus the amount
# to stop overflow
ways = [0] * (N + 1);
# Set the first way to 1 because its 0 and
# there is 1 way to make 0 with 0 coins
ways[0] = 1;
# Go through all of the coins
for i in range(len(Coins)):
# Make a comparison to each index value
# of ways with the coin value.
for j in range(len(ways)):
if (Coins[i] <= j):
# Update the ways array
ways[j] += ways[(int)(j - Coins[i])];
# return the value at the Nth position
# of the ways array.
return ways[N];
def printArray(coins):
for i in coins:
print(i);
if __name__ == '__main__':
Coins = [1, 5, 10];
print("The Coins Array:");
printArray(Coins);
print("Solution:",end="");
print(getNumberOfWays(12, Coins));
# This code is contributed by 29AjayKumar
C#
/* We have input values of N and
an array Coins that holds all of
the coins. We use data type of
long because we want to be able
to test large values without
integer overflow*/
using System;
public class getWays
{
static long getNumberOfWays(long N, long[] Coins)
{
// Create the ways array to 1 plus the amount
// to stop overflow
long[] ways = new long[(int)N + 1];
// Set the first way to 1 because its 0 and
// there is 1 way to make 0 with 0 coins
ways[0] = 1;
// Go through all of the coins
for (int i = 0; i < Coins.Length; i++)
{
// Make a comparison to each index value
// of ways with the coin value.
for (int j = 0; j < ways.Length; j++)
{
if (Coins[i] <= j)
{
// Update the ways array
ways[j] += ways[(int)(j - Coins[i])];
}
}
}
// return the value at the Nth position
// of the ways array.
return ways[(int)N];
}
static void printArray(long[] coins)
{
foreach (long i in coins)
Console.WriteLine(i);
}
// Driver code
public static void Main(String []args)
{
long []Coins = { 1, 5, 10 };
Console.WriteLine("The Coins Array:");
printArray(Coins);
Console.WriteLine("Solution:");
Console.WriteLine(getNumberOfWays(12, Coins));
}
}
// This code has been contributed by 29AjayKumar
The Coins Array:
1
5
10
Solution:
4
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。