递归地查找数组中的最大值

Finding maximum value in array recursively

本文关键字:最大值 数组 查找 递归      更新时间:2023-09-26

我正在尝试使用递归来查找JavaScript中数组的最大值。我创建了这个函数,但不知道如何递归地执行。

function Max(a) {
  var a = [2,3,5];
  return Math.max.apply(Math, a);
}
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中较大的一个。然后,该函数可以完成其以前的所有部分完成状态。

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)
}

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

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/

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

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;
}

请随意优化上述代码。您也可以在github上找到这段代码作为要点。

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减少到只有一个元素时,返回该元素并观察堆栈展开。

试试这个:

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);
}

    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]))

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

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)
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
function max(arr) {
  if (arr.length > 0) {
    return arr[arr.length - 1] > max(arr.slice(0, -1))
      ? arr[arr.length - 1]
      : max(arr.slice(0, -1));
  }
  return 0;
}

最大值([3,2,1,7,5])//7

或者使用位到达器命名:

function max(arr) {
  if (arr.length > 0) {
    const currentValue = arr[arr.length - 1];
    const nextValue = max(arr.slice(0, -1));
    return currentValue > nextValue ? currentValue : nextValue;
  }
  return 0;
}