Search code examples
javascriptrecursionbacktracking

JavaScript dual recursive call, how to pass back result?


I have one piece of JavaScript code which call recursive method twice, the result couldn't pass back:

var subSum = (nums, target) => {
    var res = [];
    var chosen = [];
    subSets(nums, chosen, target, res);
    return res;
};

var subSets = (nums, chosen, target, res) => {
  if (nums.length === 0) {
    if (sumAry(chosen) == target) {
        console.log(array2Str(chosen));
        res.push(chosen);
    }
    //console.log(array2Str(chosen));
  } else {
    let it = nums[0];
    nums.shift();
    chosen.push(it);
    subSets(nums, chosen, target, res);

    chosen.pop();
    subSets(nums, chosen, target, res);
    nums.unshift(it);
  }
};
var array2Str = (ary) => {
    if (!ary || ary.length < 1) return '';
    let res = [];
    arrayToStr(ary, res);
    return res.join("");
};
var arrayToStr = (ary, res) => {
    res.push('[');
    for(let i = 0; i < ary.length; i ++) {
        let it = ary[i];
        if (Array.isArray(it)) {
            arrayToStr(it, res);
            if (i != ary.length - 1) {
                res.push(', ');
            }

        } else {
            res.push( (i == ary.length - 1) ? `${it}` : `${it}, `);
        }
    }
    res.push(']');
};

The test code is:

let nums = [5,3,1,2,4,6];
console.log(`array2Str(subSum(nums, 7))`);

The output is:

Debugger attached.
[5, 2]
[3, 4]
[1, 2, 4]
[1, 6]
[[], [], [], []]

You can see the last line is the dump of the result array (res), and the content of 4 sub array are empty, but according the console log above, those values were pushed into the result array. anyway, if I comment out last subSets recursive call, the final result printing will not be empty. Any idea on how to pass back the result with two recursive call? I tried one global array container and it didn't either.


Solution

  • the array is passing by reference , that's way is being overwriting . use a primitive type like string , or shallow copy chosen array .

    for this change the push line to this

          res.push(chosen.slice())  // for shllow copy
    
          res.push(chosen.join())  // for using primitive string
    

    // i assume that the missing sumAry function shuld do ..
    const sumAry = array => array.reduce((a, b) => a + b, 0)
    
    
    var subSum = (nums, target) => {
      var res = []
      var chosen = []
      subSets(nums, chosen, target, res)
      return res
    }
    
    var subSets = (nums, chosen, target, res) => {
      if (nums.length === 0) {
        if (sumAry(chosen) == target) {
          console.log(array2Str(chosen))
          res.push(chosen.slice()) 
          // res.push(chosen.join()) 
        }
      } else {
        let it = nums[0]
        nums.shift()
        chosen.push(it)
        subSets(nums, chosen, target, res)
    
        chosen.pop()
        subSets(nums, chosen, target, res)
        nums.unshift(it)
      }
    }
    var array2Str = ary => {
      if (!ary || ary.length < 1) return ''
      let res = []
      arrayToStr(ary, res)
      return res.join('')
    }
    var arrayToStr = (ary, res) => {
      res.push('[')
      for (let i = 0; i < ary.length; i++) {
        let it = ary[i]
        if (Array.isArray(it)) {
          arrayToStr(it, res)
          if (i != ary.length - 1) {
            res.push(', ')
          }
        } else {
          res.push(i == ary.length - 1 ? `${it}` : `${it}, `)
        }
      }
      res.push(']')
    }
    
    let nums = [5, 3, 1, 2, 4, 6]
    console.log(array2Str(subSum(nums, 7)))