【问题标题】:Finding maximum value in array recursively递归查找数组中的最大值
【发布时间】:2015-11-05 00:44:21
【问题描述】:

我正在尝试使用递归来查找 JavaScript 数组中的最大值。我创建了该函数,但无法弄清楚如何递归地执行它。

function Max(a) {
  var a = [2,3,5];
  return Math.max.apply(Math, a);
}

【问题讨论】:

  • 递归是调用自身的函数。如果函数被传递了值数组,你想传递给内部函数调用的是什么?
  • 提示:max(a,b,c) = max(max(a,b),c)。
  • 为什么数组值设置在inside你的函数?
  • Math.max 函数在浏览器的核心代码中“在后台”执行递归(或迭代?)部分。因此,如果您的目标/任务是编写“迭代函数”,您可能应该查看here(错误的语言,正确的想法)。

标签: javascript recursion max


【解决方案1】:

这里是一个递归函数的例子,它接受一个数字数组并比较前两个,删除较小的,然后在给定的数组上再次调用自己,减去删除的数字。

function max(numArray) 
{
    // copy the given array 
    nums = numArray.slice();

    // base case: if we're at the last number, return it
    if (nums.length == 1) { return nums[0]; }

    // check the first two numbers in the array and remove the lesser
    if (nums[0] < nums[1]) { nums.splice(0,1); }
    else { nums.splice(1,1); }

    // with one less number in the array, call the same function
    return max(nums);
}

这是一个 jsfiddle:https://jsfiddle.net/t3q5sm1g/1/

【讨论】:

  • [1,2,2,3](或任何两个相邻值相等的数组)会中断
  • 这会破坏原始数组,以便唯一剩余的值是最大的。
【解决方案2】:
let max = (list) => {

  // Returns first number if list length is 1
  if (list.length === 1) return list[0]

  // Returns the greater number between the first 2 numbers in an array
  if (list.length === 2) return (list[0] > list[1]) ? list[0] : list[1]

  // If array length is 3+ (Read Below)
  const subMax = max(list.slice(1));
  return (list[0] > subMax) ? list[0] : subMax;
}

// Example
max([5,5,5,8,6,7,4,7])

了解“调用堆栈”如何用于递归非常重要。

在上面的示例中,由于数组长度超过 3,所以要调用的第一行是

const subMax = max(list.slice(1));

这一行所做的只是取出数组中的第一项并以较短的数组作为参数调用函数。这一直持续到数组长度为 2,然后返回 2 中的较大者。然后该函数可以完成其之前的所有部分完成状态。

【讨论】:

    【解决方案3】:

    ES6 语法使这非常简洁。

    const findMax = arr => {
      if (!Array.isArray(arr)) throw 'Not an array'
      if (arr.length === 0) return undefined
      const [head, ...tail] = arr
      if (arr.length === 1) return head
      return head > findMax(tail) 
        ? head
        : findMax(tail)
    }
    

    【讨论】:

      【解决方案4】:
      function max(array) {
        if (array.length === 1) {  // Step1: set up your base case
            return array[0]
       } else {  
           return Math.max(array.shift(), max(array); // Step2: rec case
       }
      }
      

      每次调用递归案例时,它都会更接近基本案例。

      Math.max 接受两个数字,然后比较它们,然后返回两者中较大的一个。

      每次调用 array.shift() 时,都会从数组中弹出数组中的第一个元素,因此递归调用中的第二个参数是将数组缩短一个。

      当 array.length 减少到只有一个元素时,返回该元素并观察堆栈展开。

      【讨论】:

        【解决方案5】:

        这实际上是我向软件职位应聘者提出的问题之一:在锯齿状数组中找到最大数。数组的每个元素可以是一个数字,也可以是不定级别的其他数字数组,如下所示:

        var ar = [2, 4, 10, [12, 4, [100, 99], 4], [3, 2, 99], 0];
        

        现在,为了好玩和保持这篇文章的简短,我将提供两个问题的解决方案。第一个解决方案使用递归,而第二个解决方案使用堆栈。事实上,所有这些递归问题也可以通过使用堆栈方法来解决。

        解决方案一:使用递归找到最大值

        // Use recursion to find the maximum numeric value in an array of arrays
        function findMax1(ar)
        {
            var max = -Infinity;
        
            // Cycle through all the elements of the array
            for(var i = 0; i < ar.length; i++)
            {
                var el = ar[i];
        
                // If an element is of type array then invoke the same function
                // to find out the maximum element of that subarray
                if ( Array.isArray(el) )
                {
                    el = findMax1( el );
                }
        
                if ( el > max )
                {
                    max = el;
                }
            }
        
            return max;
        }
        

        解决方案二:使用堆栈找到最大值

        // Use a stack to find the maximum numeric value in an array of arrays
        function findMax2(arElements)
        {
            var max = -Infinity;
        
            // This is the stack on which will put the first array and then 
            // all the other sub-arrays that we find as we traverse an array     
            var arrays = [];
        
            arrays.push(arElements);
        
            // Loop as long as are arrays added to the stack for processing
            while(arrays.length > 0)
            {
                // Extract an array from the stack
                ar = arrays.pop();
        
                // ... and loop through its elements
                for(var i = 0; i < ar.length; i++)
                {
                    var el = ar[i];
        
                    // If an element is of type array, we'll add it to stack
                    // to be processed later
                    if ( Array.isArray(el) )
                    {
                        arrays.push(el);
                        continue;
                    }
        
                    if ( el > max )
                    {
                        max = el;
                    }
                }
            }
        
            return max;
        }
        

        请随意优化上述代码。您也可以通过gist on github 找到此代码。

        【讨论】:

          【解决方案6】:

          试试这个:

          const biggestElement = list => {
              if (list.length == 1)
                  return list[0];
              if (list[0] > list[1])
                  list[1] = list[0];
              list = list.splice(1);
              return biggestElement(list);
          }
          

          【讨论】:

            【解决方案7】:

                function recursiveMaxNumber(items){ 
            
                   if(items.length === 1){
                     return items[0] //Base-case reached
                      }
                  else{
                        if(items[0]>=items[items.length-1]){
                            items.pop() //remove the last item in the array
                            return recursiveMaxNumber(items) 
                        }
                        else{
                            return recursiveMaxNumber(items.slice(1)) //remove the first item in the array
                        }
                     }
                }
                
                console.log(recursiveMaxNumber([2,22,3,3,4,44,33]))

            【讨论】:

              【解决方案8】:

              虽然它不是一个有效的方法下面是我的尝试,

              function max(a, b) {
                return a > b ? a : b
              }
              
              function findMaxOfArrayRecursion(arr) {
                if (arr.length == 1) {
                  return arr[0]
                }
                return max(arr[0], findMaxOfArrayRecursion(arr.slice(1)))
              }
              

              基本上我们假设第一个数组元素是最大值并以递归方式将其与其他元素进行比较。

              添加一个高效的非递归方法也仅供参考,

              Math.max(...arr)
              
              

              【讨论】:

                【解决方案9】:
                const getMax = (arr) => {
                    // base case
                    if(arr.length === 0) return -Infinity;
                    if(arr.length === 1) return arr[0];
                
                    // recursive case
                    return Math.max(arr[0], getMax(arr.slice(1)));
                }
                
                getMax([5, 2, 11, 9])   //11
                

                【讨论】:

                • 欢迎来到 Stack Overflow,感谢您提供答案。您能否编辑您的答案以包括对您的代码的解释?这将帮助未来的读者更好地理解正在发生的事情,尤其是那些不熟悉该语言并努力理解这些概念的社区成员。当这个问题已经有多个答案时,这一点尤其重要。在什么条件下你的方法可能更受欢迎?您是否在利用新功能?
                猜你喜欢
                • 2012-10-18
                • 2013-11-04
                • 1970-01-01
                • 1970-01-01
                • 2016-05-07
                • 2016-06-10
                • 2021-12-08
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多