堆栈和递归函数

时间:2016-07-09 02:09:15

标签: javascript arrays recursion

我希望这不是一个重复的问题 - 尽管我在这方面找不到多少帮助。

我正在练习递归函数(我是新手),我正在尝试将数组中的每个数相乘。有点像阶乘。我有这个代码,但结果只返回undefined

以下是代码:

 var stack = [];

function countDown(int) {
  stack.push(int);
  if (int === 1) {  
    return 1;
  }
    return countDown(int - 1);
}

function multiplyEach() {
  // Remove the last value of the stack 
  // and assign it to the variable int
  int = stack.pop();
  x = stack.length;
  // Base case
  if ( x === 0 ) {
    return;
  }
  // Recursive case
  else {
    stack[int - 1] = int * stack[x - 1];
    return multiplyEach(int);
  }
}

// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());

非常感谢您的任何见解。

干杯!

5 个答案:

答案 0 :(得分:2)

要解决的第一件事是你的multiplyEach()函数应该有一个名为int的参数,从它的外观来看。您使用的方法可能更适合不同的技术,但我们会做到这一点。

接下来,在multiplyEach()中,有两种可能的路径:

  1. 堆栈仍然有元素,在这种情况下,我们将堆栈上的新顶值乘以旧的值,然后继续运行另一个multiplyEach。

  2. 堆栈是空的,我们只是返回。

  3. 这里的问题是我们实际上并没有返回最终的堆栈值,或者将它留在那里以便稍后访问。我们已经有效地丢失了它,那么输出的功能是什么?

    在许多语言中,我们会为此函数定义一个返回类型,void表示无值,或int表示返回乘法值。但是,在Javascript中,没有函数不会返回值; "无"在JS中表示为undefined。当你返回multiplyEach()时,你再次将它调用到调用堆栈上,并等待一个实际的返回值......最终为return;,JS解释为return undefined; }。同样,在大多数语言中,会出现某种形式的错误,但不会出现在JS中!让我们看看两种可能的实现:

    1. 您使用的自定义堆栈:

      // your stack is fine, so we'll skip to the meat
      function multiplyEach() {
          var int = stack.pop(), x = stack.length;
          stack[x - 1] *= int;
          if(x < 2) // to multiply, we need at least two numbers left
              return;
          multiplyEach();
      }
      
      //...
      multiplyEach();
      console.log(stack[0]);
      
    2. 使用参数并使用列表:

      function multiplyEach(index) {
          var int = list[index];
          if(index == 0)
              return int;
          return int * multiplyEach(index - 1);
      }
      
      //...
      console.log(multiplyEach(list.length - 1));
      
    3. 他们以递归方式实现这两种方式;所有递归固有地要求函数调用自身。另一种可能性是使用参数存储总数,而不是像选项2中那样乘以返回值;那被称为尾递归。

      编辑:注意到选项1的基本情况是在错误的地方,所以我移动了它。它现在应该工作。

答案 1 :(得分:1)

递归地你可以这样做:

function multiplyEach(arr, size) {
  return size === 0 ? arr[size] : arr[size] * multiplyEach(arr, size - 1);
}

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(multiplyEach(array, array.length - 1));

但你可以使用原生方法reduce来做,然后你可以做到这一点:

console.log([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(function(a, b) { return a * b; }));

ES6版本:

console.log([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce((a, b) => a * b));

我希望它有所帮助。

答案 2 :(得分:1)

有时候递归更适合解决问题,有时候迭代更适合解决问题。

递归更适合执行操作,直到满足条件然后退出,类似于while循环。

迭代更适合执行 N 次操作然后退出,类似于for循环。

在我们的例子中,我们想要输入一个数组并输出该数组所有元素的乘积。换句话说,我们想要执行 N - 1 乘法,其中 N 是数组中元素的数量。由于我们知道要执行的操作数量,因此我们应该通过迭代解决我们的问题,这将在下面完成。

var arr = [1, 2, 3]
var result = multiplyEach(arr)
console.log(result)
// -> 6

function multiplyEach(arr) {
    var result = 1
    arr.map(function(value) {
        result *= value
    })
    return result
}     

请记住,虽然以上是一个近似的经验法则,因为有时递归将是比迭代更优雅的解决方案。这是真正的因子的简单,递归和优雅的实现。

function factorial(value) {
    return 1 === value ? 1 : value * factorial(value - 1)
}

factorial的迭代实现在while循环形式和循环形式中并不相同。

function factorial(value) {
    var result = 1
    while (value > 0) {
        result *= value
        value--
    }
    return result
}

function factorial(value) {
    var result = 1
    for (var i = 0; i < value; i++) {
        result *= value
    }
    return result
}

答案 3 :(得分:0)

我认为主要问题是你在multiplyEach()定义中没有参数,但你试图在函数内部调用一个参数。

这样的工作:

public void setLetterNotNew(int letterId) {

    final String sql = "UPDATE income SET isnew=? WHERE id=?";

    try( Connection con = HikariFactory.getConnection(); PreparedStatement ps = con.prepareStatement(sql); ) {

        ps.setInt(1, 0);
        ps.setInt(2, letterId);

        int i = ps.executeUpdate();
        if(i==0) throw new SQLException("setLetterNotNew");

    } catch (SQLException e) {
        log.error(e);
    }
}

答案 4 :(得分:0)

递归函数multiplyEach()中的基本情况返回undefined。

这就是你的问题所在。

一个简单的解决方法是:

var stack = [];
var multipliedStack = [];

function countDown(int) {
  stack.push(int);
  if (int === 1) {  
    return 1;
  }
    return countDown(int - 1);
}

function multiplyEach() {
  // Remove the last value of the stack 
  // and assign it to the variable int
  int = stack.pop();
  x = stack.length;
  // Base case
  if ( x === 0 ) {
    return multipliedStack.reverse();
  }
  // Recursive case
  else {
    multipliedStack.push(int * stack[x - 1]);
    return multiplyEach(int);
  }
}

// Call the function countDown(7)
countDown(7);
// And then print out the value returned by multiplyEach()
console.log(multiplyEach());

我没有完全明白你的意思“有点像一个阶乘”?该功能到底应该做什么?

要理解递归,你需要围绕递归基本情况进行包装,而且我认为你需要修改在代码中没有正确使用的push()和pop()。

如果你习惯于迭代,递归函数通常会让人感到困惑,继续尝试,你会很快习惯它。