一个数组,只考虑速度,怎么获取最大值以及最小值?

方法一:使用 Math.max 和 Math.min 结合扩展运算符

Math.max 和 Math.min 是 JavaScript 内置函数,可分别返回一组数中的最大值和最小值。结合扩展运算符 ... 能直接处理数组。

function getMaxMinByMath(arr: number[]): [number, number] {
    const max = Math.max(...arr);
    const min = Math.min(...arr);
    return [max, min];
}

const arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
const [max, min] = getMaxMinByMath(arr);
console.log(`最大值: ${max}, 最小值: ${min}`);
复杂度分析
  • 时间复杂度:O(n),扩展运算符会遍历数组中的每个元素。
  • 空间复杂度:O(n),在内部会展开数组。
  • 优点:代码简洁直观。
  • 缺点:当数组非常大时,可能会导致栈溢出错误,因为扩展运算符会一次性将数组元素展开。

方法二:手动遍历数组

手动遍历数组,在遍历过程中记录最大值和最小值。

function getMaxMinByLoop(arr: number[]): [number, number] {
    if (arr.length === 0) {
        return [NaN, NaN];
    }
    let max = arr[0];
    let min = arr[0];
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    return [max, min];
}

const arr2 = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
const [max2, min2] = getMaxMinByLoop(arr2);
console.log(`最大值: ${max2}, 最小值: ${min2}`);
复杂度分析
  • 时间复杂度:O(n),需要遍历数组中的每个元素一次。
  • 空间复杂度:O(1),只使用了常数级的额外变量。
  • 优点:不会有栈溢出风险,性能稳定,适合处理大规模数组。
  • 缺点:代码相对冗长。

方法三:使用 reduce 方法

reduce 方法可以对数组中的每个元素执行一个自定义的回调函数,并将结果累积起来。

function getMaxMinByReduce(arr: number[]): [number, number] {
    if (arr.length === 0) {
        return [NaN, NaN];
    }
    const [max, min] = arr.reduce(([accMax, accMin], current) => {
        return [
            current > accMax ? current : accMax,
            current < accMin ? current : accMin
        ];
    }, [arr[0], arr[0]]);
    return [max, min];
}

const arr3 = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
const [max3, min3] = getMaxMinByReduce(arr3);
console.log(`最大值: ${max3}, 最小值: ${min3}`);
复杂度分析
  • 时间复杂度:,会遍历数组中的每个元素。
  • 空间复杂度:,只使用了常数级的额外空间。
  • 优点:代码相对简洁,利用了数组的高阶函数。
  • 缺点:对于不熟悉 reduce 方法的开发者来说,代码理解成本较高。

方法四: 排序法

先对数组进行排序,排序后数组的第一个元素就是最小值,最后一个元素就是最大值。

function findMaxMinBySort(arr) {
    if (arr.length === 0) {
        return [null, null];
    }
    const sortedArr = [...arr].sort((a, b) => a - b);
    const min = sortedArr[0];
    const max = sortedArr[sortedArr.length - 1];
    return [max, min];
}

const array3 = [4, 6, 1, 9, 3];
const [maxResult, minResult] = findMaxMinBySort(array3);
console.log(`最大值: ${maxResult}, 最小值: ${minResult}`);

复杂度分析

  • 时间复杂度:O(nlogn),主要是排序操作的时间复杂度,常见的排序算法如快速排序、归并排序的平均时间复杂度为 O(nlogn)。
  • 空间复杂度:O(n),通常排序算法需要额外的空间来存储排序后的数组。

方法五:冒泡排序 

function getMaxMinByBubble(arr) {
    if (arr.length === 0) {
        return [null, null];
    }

    let len = arr.length;
    // 通过一轮冒泡找出最大值
    for (let i = 0; i < len - 1; i++) {
        if (arr[i] > arr[i + 1]) {
            // 交换 arr[i] 和 arr[i + 1]
            let temp = arr[i];
            arr[i] = arr[i + 1];
            arr[i + 1] = temp;
        }
    }
    // 经过一轮冒泡,最后一个元素是最大值
    let max = arr[len - 1];

    // 通过一轮反向冒泡找出最小值
    for (let i = len - 1; i > 0; i--) {
        if (arr[i] < arr[i - 1]) {
            // 交换 arr[i] 和 arr[i - 1]
            let temp = arr[i];
            arr[i] = arr[i - 1];
            arr[i - 1] = temp;
        }
    }
    // 经过一轮反向冒泡,第一个元素是最小值
    let min = arr[0];

    return [max, min];
}

const array = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
const [maxValue, minValue] = getMaxMinByBubble(array);
console.log(`最大值: ${maxValue}, 最小值: ${minValue}`);

复杂度分析

  • 时间复杂度:O(n)。虽然使用了冒泡排序的思想,但我们只进行了两轮线性的遍历操作,每轮遍历数组中的元素一次,所以总的时间复杂度为O(n) ,其中 n  是数组的长度。
  • 空间复杂度:O(1)。只使用了常数级的额外变量(如 temp 用于交换元素),没有使用额外的数据结构来存储大量数据,所以空间复杂度为常数级别。

 

性能对比与选择建议

  • 若数组规模较小,使用 Math.max 和 Math.min 结合扩展运算符的方法代码最为简洁。
  • 若数组规模较大,手动遍历数组的方法性能更稳定,不会有栈溢出风险。
  • reduce 方法在性能上和手动遍历相近,但代码简洁性介于前两者之间,适合熟悉高阶函数的开发者。
  • 排序法虽然能得到结果,但排序操作的时间复杂度较高,在只需要找出最大值和最小值的场景下,不是最优选择。

  • 冒泡虽然能获取到最大值和最小值,但相比直接遍历数组比较元素大小(手动遍历数组的方法),代码会更复杂一些,因为涉及到元素交换的操作。不过它依然是一种可行的方式,并且能在  的时间复杂度内完成任务。而和使用 Math.max 与 Math.min 或者 reduce 方法相比,代码的简洁性较差,但原理更加直观易懂,适合对算法原理进行学习和理解。

在C语言中,你可以通过递归来同时找到一个数组最大值最小值。这里是一个简单的示例,假设我们有一个未排序的一维整数数组`arr[]`,长度为`n`: ```c #include <stdio.h> // 声明两个函数指针,用于存放返回最大值最小值的函数地址 typedef int (*MinMax)(int[], int, int); // 递归函数,用于查找数组元素的当前最小值最大值 void findMinMax(int arr[], int low, int high, MinMax minFunc, MinMax maxFunc) { // 如果数组只有一个元素,直接返回该元素作为最大值最小值 if (low == high) { *minFunc(arr, low, high) = arr[low]; *maxFunc(arr, low, high) = arr[low]; } else { // 递归查找左半部分和右半部分的最小值最大值 int mid = low + (high - low) / 2; int leftMin = *minFunc(arr, low, mid); int leftMax = *maxFunc(arr, low, mid); int rightMin = *minFunc(arr + mid + 1, mid + 1, high); int rightMax = *maxFunc(arr + mid + 1, mid + 1, high); // 更新全局最大值最小值 *maxFunc(arr, low, high) = leftMax > rightMax ? leftMax : rightMax; *minFunc(arr, low, high) = leftMin < rightMin ? leftMin : rightMin; } } // 定义函数原型,分别用于返回最大值最小值 int minFinder(int arr[], int low, int high) { return arr[low]; // 这里仅作示例,实际应遍历数组找到最小值 } int maxFinder(int arr[], int low, int high) { return arr[low]; // 同样,这里仅作示例,实际应遍历数组找到最大值 } int main() { int arr[] = {5, 2, 9, 1, 7}; int n = sizeof(arr) / sizeof(arr[0]); findMinMax(arr, 0, n - 1, &minFinder, &maxFinder); printf("最小值: %d, 最大值: %d\n", minFinder(arr, 0, n - 1), maxFinder(arr, 0, n - 1)); return 0; } ``` 在这个例子中,`findMinMax`函数接受四个参数:数组、起始索引、结束索引以及指向两个辅助函数的指针,这两个辅助函数分别用于计算局部区间的最大值最小值。在主函数`main`中,我们调用`findMinMax`并打印出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值