Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何计算硬币问题的可能组合_Java_Algorithm_Combinations - Fatal编程技术网

Java 如何计算硬币问题的可能组合

Java 如何计算硬币问题的可能组合,java,algorithm,combinations,Java,Algorithm,Combinations,我试图实现一个硬币问题,问题规范是这样的 创建一个函数来计算所有可能的硬币组合,这些硬币可以用于给定的数量 All possible combinations for given amount=15, coin types=1 6 7 1) 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2) 1,1,1,1,1,1,1,1,1,6, 3) 1,1,1,1,1,1,1,1,7, 4) 1,1,1,6,6, 5) 1,1,6,7, 6) 1,7,7, 功能原型: int find

我试图实现一个硬币问题,问题规范是这样的

创建一个函数来计算所有可能的硬币组合,这些硬币可以用于给定的数量

All possible combinations for given amount=15, coin types=1 6 7 
1) 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2) 1,1,1,1,1,1,1,1,1,6,
3) 1,1,1,1,1,1,1,1,7,
4) 1,1,1,6,6,
5) 1,1,6,7,
6) 1,7,7,
功能原型:

int findCombinationsCount(int amount, int coins[])
假设硬币数组已排序。对于上面的示例,此函数应返回6

有人指导我如何实现这个吗???

使用递归

int findCombinationsCount(int amount, int coins[]) {
    return findCombinationsCount(amount, coins, 0);
}

int findCombinationsCount(int amount, int coins[], int checkFromIndex) {
    if (amount == 0)
        return 1;
    else if (amount < 0 || coins.length == checkFromIndex)
        return 0;
    else {
        int withFirstCoin = findCombinationsCount(amount-coins[checkFromIndex], coins, checkFromIndex);
        int withoutFirstCoin = findCombinationsCount(amount, coins, checkFromIndex+1);
        return withFirstCoin + withoutFirstCoin;
    }
}
int findCombinationsCount(整数金额,整数硬币[]){
返回findCombinationsCount(金额,硬币,0);
}
int findCombinationsCount(整数金额、整数硬币[]、整数checkFromIndex){
如果(金额=0)
返回1;
else if(金额<0 | | coins.length==checkFromIndex)
返回0;
否则{
int withFirstCoin=findCombinationsCount(硬币数量[checkFromIndex],硬币数量,checkFromIndex);
int without firstcoin=findCombinationsCount(金额、硬币、支票fromIndex+1);
带第一枚硬币返回+不带第一枚硬币返回;
}
}

不过,您应该检查这个实现。我这里没有Java IDE,而且我有点生疏,所以它可能有一些错误。

递归解决方案可能是正确的答案:

int findCombinationsCount(int amount, int coins[])
{
    // I am assuming amount >= 0, coins.length > 0 and all elements of coins > 0.
    if (coins.length == 1)
    {
        return amount % coins[0] == 0 ? 1 : 0;
    }
    else
    {
        int total = 0;
        int[] subCoins = arrayOfCoinsExceptTheFirstOne(coins);
        for (int i = 0 ; i * coins[0] <= amount ; ++i)
        {
            total += findCombinationsCount(amount - i * coins[0], subCoins);
        }
        return total;
    }
}
int findCombinationsCount(整数金额,整数硬币[])
{
//我假设amount>=0,coins.length>0,coins的所有元素都>0。
如果(硬币长度==1)
{
退货金额%coins[0]==0?1:0;
}
其他的
{
int-total=0;
int[]subCoins=arrayofcoinsceptthefirstone(硬币);
对于(inti=0;i*coins[0]第一个想法:

int combinations = 0;
for (int i = 0; i * 7 <=15; i++) {
    for (int j = 0; j * 6 + i * 7 <= 15; j++) {
      combinations++;
    }
}
int组合=0;

对于(int i=0;i*7而言,上述递归解决方案将起作用,但如果您添加更多的硬币面额和/或显著增加目标值,它们将非常缓慢


您需要加速的是实现一个动态编程解决方案。请看。您可以通过计算达到总数的方法的数量,而不是所需的最小硬币数量,来调整这里提到的DP解决方案,以解决您的问题。

再次使用递归测试解决方案,尽管可能不是最优雅的代码。(注意,它返回要使用的每个硬币的数量,而不是重复实际的硬币数量n次)

公共类CoinPerm{
@试验
public void QuickTest()引发异常
{
int amount=15;
整数硬币[]={1,6,7};
ArrayList solutionList=解算器(数量、硬币);
对于(解决方案:解决方案列表)
{
System.out.println(sol);
}
assertTrue(“解决方案数量错误”+solutionList.size(),solutionList.size()=6);
}
公共ArrayList SolvePerms(int amount,int coins[])引发异常
{
ArrayList solutionList=新的ArrayList();
ArrayList emptyList=新建ArrayList();
解决方案CurrentSolution=新解决方案(清空列表);
GetPerms(数量、硬币、当前解决方案、解决方案列表);
返回解决方案列表;
}
私有void GetPerms(int amount,int coins[],solution CurrentSolution,ArrayList mSolutions)引发异常
{
int currentCoin=硬币[0];

如果(currentCoin,您可以使用生成函数方法给出使用复数的快速算法

给定硬币值c1,c2,…,ck,得到求和n的方法数,你需要的是x^n的系数

(1 + x^c1 + x^(2c1) + x^(3c1) + ...)(1+x^c2 + x^(2c2) + x^(3c2) + ...)....(1+x^ck + x^(2ck) + x^(3ck) + ...)
1/(1-x^c1) * 1/(1-x^c2) * ... * (1-x^ck)
这与求x^n的系数相同

(1 + x^c1 + x^(2c1) + x^(3c1) + ...)(1+x^c2 + x^(2c2) + x^(3c2) + ...)....(1+x^ck + x^(2ck) + x^(3ck) + ...)
1/(1-x^c1) * 1/(1-x^c2) * ... * (1-x^ck)
现在使用复数,x^a-1=(x-w1)(x-w2)…(x-wa),其中w1,w2等是单位的复数根

所以

可以写成

1/(x-a1)(x-a2)....(x-am)
可以用部分分数重写的是

A1/(x-a1) + A2/(x-a2) + ... + Am/(x-am)
其中x^n的系数很容易找到:

A1/(a1)^(n+1) + A2/(a2)^(n+1) + ...+ Am/(am)^(n+1).
计算机程序应该很容易找到Ai和Ai(可能是复数)。当然,这可能涉及浮点计算

对于大n,这可能比枚举所有可能的组合要快

希望有帮助。

公共静态void main(String[]args){
public static void main(String[] args) {

    int b,c,total = 15;
    int combos =1;
        for(int d=0;d<total/7;d++)
           {
             b = total - d * 7;
            for (int n = 0; n <= b /6; n++)
        {
                    combos++;

        }

        }

      System.out.print("TOTAL COMBINATIONS  = "+combos);
}
int b,c,总计=15; 整数组合=1;
对于(int d=0;d虽然递归可以工作,并且通常是在一些大学级别的算法和数据结构课程中实现的任务,但我相信“动态规划”实现更有效

public static int findCombinationsCount(int sum, int vals[]) {
        if (sum < 0) {
            return 0;
        }
        if (vals == null || vals.length == 0) {
            return 0;
        }

        int dp[] = new int[sum + 1];
        dp[0] = 1;
        for (int i = 0; i < vals.length; ++i) {
            for (int j = vals[i]; j <= sum; ++j) {
                dp[j] += dp[j - vals[i]];
            }
        }
        return dp[sum];
    }
public static int find组合计数(int sum,int vals[]){
如果(总和<0){
返回0;
}
如果(VAL==null | | VAL.length==0){
返回0;
}
int dp[]=新的int[sum+1];
dp[0]=1;
对于(int i=0;ipackage算法;
导入java.util.Random;
/**`在这里输入代码`
*所有者:Ghodrat Naderi
*电子邮件:纳德利。ghodrat@gmail.com
*日期:12月10日
*时间:下午四时五十分
*IDE:IntelliJ IDEA 11
*/
公共类问题
{
公共静态void main(字符串[]args)
{
int[]硬币={1,3,5,10,20,50,100,200,500};
整数金额=新随机数().nextInt(10000);
int coinscoint=0;
系统输出打印项次(“金额=”+金额);
int[]numberOfCoins=findNumberOfCoins(硬币,金额);
for(int i=0;i0)
{
System.out.println(“coins=“+coins[i]+”Count=“+numberOfCoins[i]+”\n”);
coinsCount+=硬币数量[i];
}
}
System.out.println(“numberOfCoins=“+coinsCount”);
}
私有静态int[]findNumberOfCoins(int[]硬币,int金额)
{
int c=硬币长度;
int[]numberOfCoins=新的int[coins.length];
而(金额>0)
{
c--;
如果(金额>=硬币[c])
{
整数商=金额/硬币[c];
金额=金额-硬币[c]*商;
numberOfCoins[c]=商;
}
}
返回硬币数目;
}
}
<
 def countChange(money: Int, coins: List[Int]): Int = {
    def reduce(money: Int, coins: List[Int], accCounter: Int): Int = {
        if(money == 0) accCounter + 1
        else if(money < 0 || coins.isEmpty) accCounter
        else reduce(money - coins.head, coins, accCounter) + reduce(money, coins.tail, accCounter)
   }

   if(money <= 0 || coins.isEmpty) 0
   else reduce(money, coins, 0)
}
x**d - 1 = product from i=0 to d-1 of (x - g**((p-1)*i/d)) [modulo p].
sign / product from j=0 to m-1 of (a(j) - x) =
    sum from j=0 to m-1 of A(j)/(a(j) - x) [modulo p],
sum from j=0 to m-1 of A(j) * (1/a(j))**(n+1).
public static void main(String[] args){
    int[] coins = new int[]{1,2,3,4,5};
    int money = 600;
    int[][] recorder = new int[money+1][coins.length];
    for(int k=0;k<coins.length;k++){
        recorder[0][k] = 1;
    }
    for(int i=1;i<=money;i++){
        //System.out.println("working on money="+i);
        int with = 0;
        int without = 0;

        for(int coin_index=0;coin_index<coins.length;coin_index++){
            //System.out.println("working on coin until "+coins[coin_index]);
            if(i-coins[coin_index]<0){
                with = 0;
            }else{
                with = recorder[i-coins[coin_index]][coin_index];
            }
            //System.out.println("with="+with);
            if(coin_index-1<0){
                without = 0;
            }else{
                without = recorder[i][coin_index-1];
            }
            //System.out.println("without="+without);
            //System.out.println("result="+(without+with));
            recorder[i][coin_index] =  with+without;
        }
    }
    System.out.print(recorder[money][coins.length-1]);

}
countCombinations(200,new int[]{5,2,3,1} , 0, 0,new Integer[6][200+5]);

static int countCombinations(Integer targetAmount, int[] V,int currentAmount, int coin, Integer[][] memory){

    //Comment below if block if you want to see the perf difference
    if(memory[coin][currentAmount] != null){
        return memory[coin][currentAmount];
    }

    if(currentAmount > targetAmount){
        memory[coin][currentAmount] = 0;
        return 0;
    }
    if(currentAmount == targetAmount){
        return 1;
    }      
    int count = 0;
    for(int selectedCoin : V){
        if(selectedCoin >= coin){                
            count += countCombinations(targetAmount, V, currentAmount+selectedCoin, selectedCoin,memory);
        }
    }        
    memory[coin][currentAmount] = count;        
    return count;
}
public static long makeChange(int[] coins, int money) {
    Long[][] resultMap = new Long[coins.length][money+1];
    return getChange(coins,money,0,resultMap);
}

public static long getChange(int[] coins, int money, int index,Long[][] resultMap) {
    if (index == coins.length -1) // if we are at the end      
        return money%coins[index]==0? 1:0;
    else{
        //System.out.printf("Checking index %d and money %d ",index,money);
        Long storedResult =resultMap[index][money];
        if(storedResult != null)
            return storedResult;
        long total=0;
        for(int coff=0; coff * coins[index] <=money; coff ++){

             total += getChange(coins, money - coff*coins[index],index +1,resultMap);
        }
        resultMap[index][money] = total;
        return total;

    }
}
#include<iostream>
using namespace std;

int solns = 0;

void countComb(int* arr, int low, int high, int Val)
{
    bool b = false;
    for (size_t i = low; i <= high; i++)
    {
        if (Val - arr[i] == 0)
        {
            solns++;
            break;
        }
        else if (Val - arr[i] > 0)
            countComb(arr, i, high, Val - arr[i]);
        
    }
}

int main()
{
    int coins[] = { 1,2,5 };
    int value = 7;
    int arrSize = sizeof(coins) / sizeof(int);
    countComb(coins,0, arrSize,value);
    cout << solns << endl;
    return 0;
}