递归函数中断if语句javascript
我正在尝试编写一个函数,将一个数量转换为指定数量的硬币。为此,我在自己调用一个函数(我认为这是递归编程?)。我有两个问题递归函数中断if语句javascript,javascript,if-statement,recursion,Javascript,If Statement,Recursion,我正在尝试编写一个函数,将一个数量转换为指定数量的硬币。为此,我在自己调用一个函数(我认为这是递归编程?)。我有两个问题 当我在if语句的else部分调用函数本身时,我得到了错误消息。“超出了最大调用堆栈大小”?不确定这是为什么,因为上面的调用是相同的,并且在注释掉第二个调用时工作良好 另外,当第二个调用被注释掉并且函数运行时,变量total应该随着每次调用增加1。但是它并没有超过1。我想这可能是因为变量在每次调用时都被重置为0。但是,余数变量也设置为0,每次都会减小其值 有人能解释一下这里发生
if
语句的else
部分调用函数本身时,我得到了错误消息。“超出了最大调用堆栈大小”?不确定这是为什么,因为上面的调用是相同的,并且在注释掉第二个调用时工作良好total
应该随着每次调用增加1。但是它并没有超过1。我想这可能是因为变量在每次调用时都被重置为0。但是,余数
变量也设置为0,每次都会减小其值function amountCoins(amt, coins) {
var remainder = 0;
total = 0;
if(amt >= coins[0]) {
total += 1;
remainder = (amt - coins[0]);
return amountCoins(remainder, coins);
} else {
coins.shift();
//return amountCoins(remainder,coins);
}
alert(total);
}
amountCoins(121,[20,15,6,1]);
如果我是你,我会使用常规的
for
循环:
var amt = 121;
var coins = [20, 15, 6, 1];
var coinsUsed = {};
var totalCoins = 0;
for (var i = 0; i < coins.length; i++) {
if (coins[i] <= amt) {
coinsUsed[coins[i]] = Math.floor(amt / coins[i]);
amt -= coinsUsed[coins[i]] * coins[i];
totalCoins += coinsUsed[coins[i]];
} else {
coinsUsed[coins[i]] = 0;
}
}
console.log(coinsUsed, totalCoins);
问题是你的算法永远不会结束。每个递归函数都必须有一个端点,否则将产生堆栈溢出,因为递归调用存储在堆栈中 这将是一个解决方案:
function amountCoins(amt, coins, total) {
var remainder = 0;
total = total || 0; //Default value 0 (for the first call)
if(coins.length == 0) return total; //This is the ending condition (no coins)
if(amt >= coins[0]) {
total += 1;
remainder = (amt - coins[0]);
return amountCoins(remainder, coins, total);
} else {
coins.shift();
return amountCoins(remainder, coins, total);
}
}
var coins = amountCoins(121,[20,15,6,1]); //Returns: 6
alert(coins);
如您所见,我将total
转换为一个参数,这样我们就可以在调用之间存储它
希望这有帮助。干杯我想这就是你想要做的:
function amountCoins(amt, coins) {
var remainder = 0;
if(coins.length == 0) {
return 0;
} else if(amt >= coins[0]) {
remainder = (amt - coins[0]);
return amountCoins(remainder, coins)+1;
} else {
coins.shift();
return amountCoins(remainder,coins);
}
}
var total = amountCoins(121,[20,15,6,1]);
alert(total)
这里有一些东西
错误的含义
在您的程序中,逻辑上,终止条件是当硬币用完时。那么
coins.length==0
检查是否返回一个0
总数(这反过来会使向上的链种子化)将解决问题
returnamountcoins(余数,coins)+1代码>
最后,这个问题可以很容易地用for循环实现。尝试通过解开递归调用链来进行思考,您将找到一个循环解决方案。对原始代码的更正将有效:
function amountCoins(amt, coins, total) {
total = total || 0;
if (amt === 0) return total;
// throw out all the coins that are too big
while (amt < coins[0]) coins.shift();
// use the largest coin possible, then recurse
total += 1;
remainder = amt - coins[0];
return amountCoins(remainder, coins, total);
}
alert(amountCoins(121,[20,15,6,1])); // alerts 7
函数amountCoins(amt,coins,total){
总计=总计| | 0;
如果(金额===0)返回总计;
//扔掉所有太大的硬币
而(amt
如果。。。else语句,逻辑更清晰一些。imo您必须返回总计,不仅是在没有剩余硬币的情况下,而且在最后一枚硬币的价值大于剩余价值的情况下:
function amountCoins(amt, coins, total) {
total = total || 0;
if (coins.length == 0 || (amt < coins[0] && coins.length == 1)) return total;
if (amt >= coins[0]) {
total += 1;
remainder = (amt - coins[0]);
return amountCoins(amt - coins[0], coins, total);
} else {
coins.shift();
return amountCoins(remainder, coins, total);
}
}
函数amountCoins(amt,coins,total){
总计=总计| | 0;
如果(coins.length==0 | |(amt=硬币[0]){
总数+=1;
余数=(金额-硬币[0]);
返回金额硬币(金额-硬币[0],硬币,总计);
}否则{
硬币。移位();
返回金额硬币(剩余、硬币、总数);
}
}
您可以使用.reduce()
作为替代方法
我们并不需要简单数学能够处理的循环
var total = [20,15,6,1].reduce(function(obj, denomination) {
return {
total: obj.total + Math.floor(obj.amount / denomination),
amount: obj.amount % denomination
};
}, {amount:121, total:0}).total;
或者迭代数组
var arr = [20,15,6,1], amount = 121, total = 0;
for (var i = 0; i < arr.length; ++i) {
total += Math.floor(amount / arr[i]);
amount %= arr[i];
}
var arr=[20,15,6,1],金额=121,总计=0;
对于(变量i=0;i
您必须有一个非递归返回,调用链可以在这里结束。如果没有,函数将无限地调用自身并填充堆栈。这就是为什么“超过了最大调用堆栈大小”。当coins数组为空时,一个好的退出点可能是,在这种情况下,您应该返回total。函数应该返回指定数量所需的总硬币的最小数量。我认为在递归中保持变量值就是在参数中使用它是对的吗?reduce的出色使用
var arr = [20,15,6,1], amount = 121, total = 0;
for (var i = 0; i < arr.length; ++i) {
total += Math.floor(amount / arr[i]);
amount %= arr[i];
}