Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Algorithm 最小硬币兑换(有限供应),时间复杂度更高_Algorithm_Recursion_Optimization_Data Structures_Dynamic Programming - Fatal编程技术网

Algorithm 最小硬币兑换(有限供应),时间复杂度更高

Algorithm 最小硬币兑换(有限供应),时间复杂度更高,algorithm,recursion,optimization,data-structures,dynamic-programming,Algorithm,Recursion,Optimization,Data Structures,Dynamic Programming,这个问题需要用户返回一个最小硬币列表作为更改。例如,[.01、.10、.25]、.40。和(所有硬币都有10个供应数量)应返回[.10、.10、.10、.10],但不返回[.25、.1、.01、.01、.01、.01、.01] 贪婪的方法行不通。这个问题就是动态规划问题。所述溶液为O(2^n)。我们如何使用自底向上的方法将其优化到O(n^2)或更好 class CoinChange { public static List<Double> findMinRefundComb

这个问题需要用户返回一个最小硬币列表作为更改。例如,[.01、.10、.25]、.40。和(所有硬币都有10个供应数量)应返回[.10、.10、.10、.10],但不返回[.25、.1、.01、.01、.01、.01、.01]

贪婪的方法行不通。这个问题就是动态规划问题。所述溶液为O(2^n)。我们如何使用自底向上的方法将其优化到O(n^2)或更好


class CoinChange {


  public static List<Double> findMinRefundCombination(List<Double> inputCoins, double refundToMake) {
      List<Double> minCoins = new ArrayList<>();
      List<Double> coinsAccumulatedSoFar = new ArrayList<>();
      double refundSoFar = 0.0d;
      findMinRefundCombinationHelper(inputCoins, refundToMake, minCoins,coinsAccumulatedSoFar, 0, refundSoFar);
      System.out.println(minCoins.size());
      return minCoins;
  }


  public static void findMinRefundCombinationHelper(List<Double> inputCoins, double refundToMake, List<Double> minCoins, List<Double> coinsAccumulatedSoFar, int curIndex, double refundSoFar) {

    if(refundSoFar > refundToMake || curIndex == inputCoins.size()) {
      return;
    }

    if(refundSoFar == refundToMake) {
      if(minCoins.isEmpty()) {
        for(Double coin: coinsAccumulatedSoFar)
          minCoins.add(coin);
      } else {
         if(coinsAccumulatedSoFar.size() < minCoins.size()) {
           minCoins.clear();
           for(Double coin: coinsAccumulatedSoFar)
              minCoins.add(coin);
         } 
      }
    }


    coinsAccumulatedSoFar.add(inputCoins.get(curIndex));
 //   findMinRefundCombinationHelper(inputCoins, refundToMake, minCoins, coinsAccumulatedSoFar,curIndex,refundSoFar + inputCoins.get(curIndex));    
   findMinRefundCombinationHelper(inputCoins, refundToMake, minCoins, coinsAccumulatedSoFar, curIndex + 1, refundSoFar + inputCoins.get(curIndex)); 
    coinsAccumulatedSoFar.remove(coinsAccumulatedSoFar.size() - 1);
    findMinRefundCombinationHelper(inputCoins, refundToMake, minCoins, coinsAccumulatedSoFar, curIndex + 1, refundSoFar);
  }

  public static void main(String[] args) {
    List<Double> inputCoins = new ArrayList<>();
    inputCoins.add(.01);
    // inputCoins.add();
    inputCoins.add(.10);
    inputCoins.add(.25);
    inputCoins.add(0.50);
    inputCoins.add(1.0);
    double refundToMake = 0.40;
    List<Double> minCoins = findMinRefundCombination(inputCoins, refundToMake);
    for(Double coin: minCoins) 
      System.out.print(coin + " ");
    System.out.println();
  }
}

阶级变革{
公共静态列表findMinRefundCombination(列表输入硬币,双倍退款){
List minCoins=new ArrayList();
List coinsAccumulatedSoFar=new ArrayList();
双倍退款截止日期=0.0d;
findMinRefundCombinationHelper(输入硬币、退款制造、minCoins、硬币累计金额、0、退款金额);
System.out.println(minCoins.size());
归还硬币;
}
public static void findMinRefundCombinationHelper(列出inputCoins、double ReturnToMake、List minCoins、List Coins累计金额、int curIndex、double ReturnsFar){
if(refundSoFar>refundToMake | | curIndex==inputCoins.size()){
回来
}
如果(退款金额==退款金额){
if(minCoins.isEmpty()){
用于(双币:累积到目前为止的硬币)
minCoins.add(硬币);
}否则{
如果(硬币累计到当前大小()
如果您试图表示的金额足够低,则此问题可以转化为背包的变化

在注释中,您声明所有数字的精度为小数点后两位,因此所有数字都可以通过乘以100转换为整数。让我们也从原始输入中给出的每个硬币中创建10个硬币,并声明我们最多可以使用每个新硬币一次

这里的想法类似于背包:让我们引入一个函数
F(k,i)
,它表示如果我们只使用一些前
i
硬币,我们需要多少硬币才能获得sum
k
。例如,
F(0,i)
是0,因为对于我们可用的任何硬币子集,我们都可以不使用它们来实现和0
F(k>0,0)
是未定义的,因为我们无法在不使用硬币的情况下获得大于0的总和,
F(|第一枚硬币的值|,1)
等于1。请注意,
F(k,10N)
将是问题的答案


这里的循环关系是
F(k,i)=min(F(k,i-1),F(k-|硬币i |,i-1的值))
对于
k,i
的适用值。在英语中,我们说“要么我们使用第i个硬币,在这种情况下,总和必须增加其值,要么我们没有增加”。

数字可以有多少位精度?精度是小数点后2位,最多0.01如果每个硬币的数量不限,则dp代表每个可能的值,跟踪生成该值所需的最少硬币数量。dp[i]=min(dp[i-0.01],dp[i-0.1],dp[i-0.25],dp[i-0.4])+1。如果该值处的dp不为null,则缺少一些要处理的if,但这就是问题所在。不确定如何限制10枚硬币的使用您是否建议自下而上的方法?这里的时间复杂性是什么?O(N^3)?在这种情况下,不管你是自下而上还是自上而下。时间复杂度不能仅用N来表示——您试图改变的值也很重要。放弃100的乘法,从每一个硬币中创造10个硬币(因为这些是常数),我们看的是O(K*N)算法的复杂性。这是NP难吗?不仅是NP难,也是NP完全的。