请帮助我理解这个递归函数

Please help me understand this recursion function

本文关键字:递归函数 帮助      更新时间:2023-09-26

我正在努力理解这个递归函数,以便更好地了解递归的一般知识。我似乎不明白这个代码是怎么运作的。我希望有人能告诉我这是怎么回事这样我就能明白了。这个函数取数组中的最大值,并检查是否有数字的组合加起来等于这个值。

function ArrayAdditionI(arr) {
  arr.sort(function(a,b){  //sort array;
    return a - b;
  });
  console.log('Sorted Array: ['+arr+']');
  var largest = arr.pop();  //grab last value aka largest
  function recursion(target, array){
    if(array.length === 0) {  //if array is empty return boolean
        return target === 0;
    }
    var n = array[0];       //first value of array
    array = array.slice(1);
    console.log('Array: [' +array+']');
    console.log('Target: '+target);
    return recursion(target,array) || recursion(target - n, array);   //not exactly sure about this ???
  }
  return recursion(largest,arr);  //call recursion function
}
console.log(ArrayAdditionI([4,6,21,10,20,1]));

下面是我调用这个函数得到的结果。我已经对它们进行了评论,以显示我在哪里迷路了。

Sorted Array: [1,4,6,10,20,21] 
Array: [4,6,10,20]  //first value and largest value removed
Target: 21          //target highest value
Array: [6,10,20]    //first value removed again
Target: 21          //still 21
Array: [10,20]      //another value removed
Target: 21
Array: [20]         //last value in array
Target: 21
Array: []           //empty array.. Why did this not return a false???
Target: 21          
Array: []           //why is it doing this twice?
Target: 11          //where in the world did this come from. I see 21 - 10 but how did that happen?
Array: [20]         //When did this value get added back to the array?
Target: 15          //Totally lost at this point...
Array: []
Target: 15
Array: []
Target: 5
Array: [10,20]      //Where are these values coming from?
Target: 17
Array: [20]
Target: 17          //why does the target keep changing??
Array: []          
Target: 17
Array: []           
Target: 7
Array: [20]
Target: 11          //from 17 to 7 then back to 11?
Array: []
Target: 11
Array: []           //Empty arrays still not returning false??
Target: 1
Array: [6,10,20]    //No idea how these combinations are being generated.
Target: 20
Array: [10,20]
Target: 20
Array: [20]
Target: 20
Array: []
Target: 20
true                //Right answer but how?

我希望这能让你走上正轨:

Array:[]//空Array ..为什么不返回false??

因为检查完成时数组不是空的。当slice调用删除最后一项时,它变为空。当进入函数的数组为空时,后面的调用将返回false。

Array:[]//为什么要做两次?

因为表达式recursion(target,array) || recursion(target - n, array)。它们中的每一个都使用一个包含单个元素的数组来调用,当它们删除该元素时将显示一个空数组。

Target: 11//这到底是从哪里来的?我看到了21- 10,但这是怎么发生的?

表示target == 21n == 10被调用时的recursion(target - n, array)

Array:[20]//这个值是什么时候被添加回数组的?

没有加回去,它是一个不同的数组。递归已经达到极限,它退回到前一个状态来尝试下一个可能性。

目标:15//此时完全丢失…

target == 21n == 6被调用时,recursion(target - n, array)被调用。

Array:[10,20]//这些值是从哪里来的?

这是另一个退步。每个递归级别将状态存储在堆栈中,以便它可以备份到前一个状态。

Target: 17//为什么Target不断变化??

因为代码正在尝试不同的组合进入recursion(target - n, array)调用的路径。函数被调用时,target的值为一个新值。

Array:[]//空数组仍然不返回false??

是的,他们有。每个空数组结束一个可能的组合,并使代码返回并尝试下一个组合。

Array:[6,10,20]//不知道这些组合是如何生成的

通过跟踪到数组为[4,6,10,20]的状态并切断4

true//正确答案,但如何?

通过找出所有可能的组合,直到找到正确的组合。

我不确定您是否可以将其视为答案,但请查看。这是你自己的代码,没有hack和更好的诊断:

function ArrayAdditionI(arr) {
    arr.sort(function (a, b) { //sort array;
        return a - b;
    });
    console.log('Sorted Array: [' + arr + ']');
    var largest = arr.pop(); //grab last value aka largest
    function recursion(target, array, level) {
        level++;
        console.log("Level: "+level);
        console.log("Entering: " + target + " [" + array + "]");
        if (array.length === 0) { //if array is empty return boolean
            console.log("Array empy, is target 0? " + (target === 0));
            result = (target === 0);
        } else {
            var n = array[0]; //first value of array
            array = array.slice(1);
            console.log('Calling return: target=' + target + ', n=' + n + ', ' + '[' + array + ']');
            var result = recursion(target, array, level);
            if (result === true){ 
                console.log("Path 1: true");
            } else {
                result = recursion(target - n, array, level);
                console.log("Path 2: "+result);
            }
        }
        console.log('Returning level='+level+': '+result);
        console.log(); //spacer
        level--;
        return result;
    }
    return recursion(largest, arr, 0); //call recursion function
}