有人可以解释一下这个递归函数是如何工作的。我无法理解如何在调用堆栈中返回值。你能解释一下代表执行环境的图形吗?如果你可以解释Udemy课程中解释的方式,那就更好了 - 理解奇怪的部分。
function findSolution(target) {
function find(start, history) {
if (start == target)
return history;
else if (start > target)
return null;
else
return find(start + 5, "(" + history + " + 5) ") || find(start * 3, "(" + history + " * 3) ");
}
return find(1, "1");
}
console.log(findSolution(13));
答案 0 :(得分:1)
你所拥有的是一个具有两个退出条件的递归函数,一个用于找到的结果,其中start和target值相等,这将返回历史记录,一个起始值大于目标值,返回{ {1}}找不到结果。
递归machanis是在两个方向上分支函数的调用,一个是添加fice,另一个是将值乘以三。
分支以logical OR ||
进行,这意味着如果第一个分支返回truthy结果,则会获得此结果,而从不调用另一个分支。如果第一个分支返回null
,falsy值,则调用第二个分支。
你最终得到的是一棵带树枝和测试的树。
null
这意味着,在第一次通话时,它以1开头,如有必要则转到2和3,依此类推。
要想出一个主意,你可以在console.log中添加一个关卡变量,并观察每个级别的内容。
1 level 0 / \ 2 5 level 1 / \ / \ 3 4 6 7 level 2
level, start, history action
-------------------------------------------- ----------------
0 1 1 check next level
1 6 (1 + 5) check next level
2 11 ((1 + 5) + 5) check next level
3 16 (((1 + 5) + 5) + 5) null
3 33 (((1 + 5) + 5) * 3) null
2 18 ((1 + 5) * 3) null
1 3 (1 * 3) check next level
2 8 ((1 * 3) + 5) check next level
3 13 (((1 * 3) + 5) + 5) found
(((1 * 3) + 5) + 5) result
function findSolution(target) {
function find(start, history, level) {
level = level || 0;
console.log(level, start, history);
if (start == target) return history; // exit condition 1 (found)
if (start > target) return null; // exit condition 2 (not found)
return find(start + 5, "(" + history + " + 5) ", level + 1) ||
find(start * 3, "(" + history + " * 3) ", level + 1);
}
return find(1, "1");
}
console.log(findSolution(13));
答案 1 :(得分:0)
尝试绘制了几个执行案例供您参考。我想这里唯一棘手的部分是行return find(start + 5, "(" + history + " + 5) ") || find(start * 3, "(" + history + " * 3) ");
可能不明显的是||
被称为short circuit or in JS。这意味着,如果我们var x = a || b
b
仅在a
不真实的情况下进行评估。
在您的问题的上下文中,提到的行基本上是说“尝试沿着添加5的路径,并且仅在此失败的情况下(即,返回null)尝试沿着乘以3的路径前进。
这里的递归函数find
基本上有三种情况:
start == target
是真的,这意味着我们已经通过解决方案到达了递归的末尾。这将返回历史记录字符串start > target
为真,这意味着我们已超越目标,返回null表示此路径未导致解决方案Try going down the path of adding 5
。如果这不起作用(我们返回null),try going down the path of multiplying 3
。示例案例:
findSolution(0) //target=0
find(1, "1") //This goes to Case 3
find(1+5,"(1 + 5)") || find(1*3,"(1 * 3)")
find(1+5,"(1 + 5)") // This is a Case 2, returns null, try multiplying by 3 now
find(1*3,"(1 * 3)") // This is Case 2 again, returns null
null || null //Both paths lead to null, stop recursing, return null
null
null
findSolution(1) //target=1
find(1,"1") // This leads to the case 1. Return the history string
"1"
"1"
findSolution(3) //target = 3
find(1,"1") //This leads to case 3
find(1+3,"(1 + 5)") || find(1*3,"(1 * 3)")
find(1+5,"(1 + 5)") // This is a Case 2, returns null, try multiplying by 3 now
find(1*3, "(1 * 3)") // This is a case 1, return History string, recursion ends
null || "(1 * 3)"
"(1 * 3)"
"(1 * 3)"
findSolution(8) //target=8
find(1,"1") //This leads to case 3
find(1+5,"(1 + 5)") || find(1*3,"(1 * 3)") // Evaluate lhs first
find(1+5,"(1 + 5)") // This is a case 3 scenario again
find(6 + 5,"((1 + 5) + 5)") || find(6 * 3, "((1 + 5) * 3)")
find(6 + 5,"((1 + 5) + 5)") // Case 2, returns null
find(6 * 3, "((1 + 5) * 3)") // Case 2, returns null
null || null //Going down the add 5 path failed here, try multiplying 3
find(1*3,"(1 * 3)") // This is a case 3
find(3 + 5, "((1*3)+5)") || find(3 * 3, "((1 * 3) * 3")
find(8,"((1*3)+5)") // This is case 1, recursion ends, return history
"((1*3)+5)"
"((1*3)+5)" || find(..) //LHS evaluated to true, no need to do rhs
"((1*3)+5)"
"((1*3)+5)"
"((1*3)+5)"
"((1*3)+5)"
答案 2 :(得分:-1)
简单来说,
递归函数是一个在执行过程中调用自身的函数。这使函数能够多次重复,输出结果和每次迭代的结束。
递归函数在计算机科学中很常见,因为它们允许程序员使用最少量的代码编写高效的程序。
缺点是如果写得不正确,它们会导致无限循环和其他意外结果。
递归函数开发和执行是基于编程的复杂性和本质的变体。如果我们只是假设要为任何高达100的值递归递增值,那么可能它实际上很容易实现,但在真实的编程环境中,我们面临着许多复杂的问题。
function increment(start){
if(start < 100){
start++;
increment(start);
console.log(start);
}else{
console.log("value reached to 100");
}
}
increment(0);
在这段代码中,我使用了递增函数,递增1。
increment(0);
这是函数调用,我可以将初始值指定为0,它将在函数中以1开始递增。
if(start < 100){
start++;
increment(start);
console.log(start);
}else{
console.log("value reached to 100");
}
我把比较限制高达100,所以我的函数调用了101次。一旦达到极限并且(开始&lt; 100)条件为false,它将显示else代码消息。
如果我没有给出100的限制,那么它进入无限循环并且javascript调用堆栈最大大小超过错误或者浏览器可能进入无限循环。
希望我的解释可以帮到你。请查看网站,这对您理解递归和递归方法肯定有帮助。