我试图理解我为一个问题找到的解决方案:“给你不同面额的硬币和总金额。写一个函数来计算组成该金额的组合数。你可以假设每种硬币的数量是无限的。”
我的问题是,如果我用change(3,[2])运行函数,为什么它会输出0。我很难理解在一个递归调用currentCoin变得未定义之后,当程序到达该调用中的for循环时,它是如何不再调用change函数的total=change(amount-0*undefined,coins.slice(0,-1))
。为什么它不会在change(NaN,[])
或coins的无限递归调用中崩溃。片(0,-1)
正在空数组上使用。在for循环中似乎忽略了这一点。
我是否误解了for循环的工作原理?
var change = function(amount, coins) {
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1];
let total = 0;
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
}
return total;
};
console.log(change(3,[2]))
var change = function(amount, coins) {
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1]; // firstpass 1-1 = 0, second pas 0-1=-1 => coins[-1] = undefined
let total = 0;
// this will 0*0<=3, second pass 0*undefined => null which is false hence never execute
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
}
return total;
};
console.log(change(3,[2]))
在第二次通过时coins.length=0那么
let currentCoin = coins[0 - 1]; // = undefined
稍后在for循环中,您将看到0*undefined(qty*currentCoin),这将导致不是数字的NaN
不是崩溃,因为一个NaN与一个数字相比是完全错误的。。。楠
qty * currentCoin <= amount
evaluate为false,将退出for。
所以,如果你需要检查NaN,你必须在
let totalCoin = qty * currentCoin;
let check = isNaN(totalCoin);
if(check) {
// return you sentinel value;
}
这里发生了几件事。
首先是硬币[coins.length-1]
的行为。在Javascript中,当您在列表中不存在的索引处访问列表的元素时,索引器将返回undefined
,而不是使用IndexOutOfBoundsException
或类似方法崩溃。
第二个是qty*currentCoin
把这些放在一起,您会看到,在第一次递归中,
coins
数组将为空,这使得currentCoin
NaN。这导致数量*currentCoin
如果您在有关函数的战略位置插入
console.log
调用,则会更清楚发生了什么:
var change = function(amount, coins) {
console.log(amount, coins);
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1];
console.log(':', currentCoin, amount);
let total = 0;
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
console.log('=', total);
}
console.log('recdone');
return total;
};
console.log(change(3,[2]))
问题内容: 这两种获取阶乘(循环与递归)的方法中哪种更有效/更快?如果可以改进,那又如何呢? 语言:Java 问题答案: 因为没有方法调用的开销,所以for循环将更加有效。(作为一般规则,循环几乎总是比递归更有效率) 为了解释为什么您必须深入了解调用方法和调用堆栈时发生的事情。 基本上,当您调用一个方法时,它需要一些空间来使用(例如其局部变量之类的东西),它还需要空间以用于将传入的参数传递给它,并
问题内容: 是否每个递归函数都有一个等效的for循环?(两者都达到相同的结果)。 我有这个递归函数: 假设单词是Set [],并且单词[i] =单词长度为i的集合。 我想做的是:使用一个单词(例如,“ stackoverflow”,没有空格)启动递归,我试图查找该单词是否可以切成子单词(“ stack”,“ over”,“ flow”) ..子词的最小长度为3,并且假设长度为i的子词在Set wo
我在一个名为“y”的列表中有一个大约28K个数字的列表,我正在API上运行for循环来发送消息,但这需要很多时间(确切地说,每次调用1.2797秒) 代码: 我怎样才能减少做这件事的时间?
我正在编写一个计算e^x值的方法。我在python中实现它的方式如下。 这将很好地返回e^x的值。但是,当我尝试在c#中实现相同的方法时,它没有输出与python中相同的值。以下是c#中的实现。 起初,这段代码的输出是一个无穷大符号。为了解决这个问题,我只是减少了循环运行的次数。在c#中,循环只运行10次,代码的输出非常接近于python中循环运行100次的输出。我的问题是,在不同的编程语言中,两
if语句 (实际上是if表达式) OCaml有两种if语句: if boolean-condition then expression if boolean-condition then expression else other-expression 不同于传统的语言,if语句是表达式。它们更类似于C类语言中的三元操作符?: 而不是你所熟悉的if语句。 下面是if语句的简单例子: # le