我们经常碰到一个问题,就是需要在一个数组中求最大值或者最小值。如果我们要同时取出最大最小值呢?
常见的做法是扫描一次数字,然后分别和当然最大值和当前最小值进行比对,因此总的比较次数是2N,
其中N为数组的长度。
那么有没有办法减少比较次数呢?
function quickSort(array, lowIndex, highIndex) {
if (lowIndex < highIndex) {
const pivotIndex = partition(array, lowIndex, highIndex)
quickSort(array, lowIndex, pivotIndex - 1)
quickSort(array, pivotIndex + 1, highIndex)
}
}
function partition(array, lowIndex, highIndex) {
const pivotValue = array[highIndex];
let lowerIndex = lowIndex - 1;
for (let i = lowIndex; i <= highIndex - 1; i++) {
if (array[i] < pivotValue) {
lowerIndex++;
const temp = array[lowerIndex];
array[lowerIndex] = array[i];
array[i] = temp;
}
}
const temp = array[lowerIndex + 1];
array[lowerIndex + 1] = array[highIndex];
array[highIndex] = temp;
return lowerIndex + 1;
}
let i = 0;
const randArray = [];
while(i < 20) {
randArray.push(Math.floor(Math.random() * Math.floor(100)));
i++;
}
quickSort(randArray, 0, randArray.length - 1)
console.log('Array:', randArray);
console.log('Smallest value:', randArray[0]);
console.log('Biggest value:', randArray[randArray.length - 1]);
``` .js
/**
return {
max,
min,
count
};
}
var timestart = new Date().getTime();
console.log(findMaxAndMin([1, 2, 3, 3, 4, 5, 5, 7]));
console.log(findMaxAndMin([7, 6, 5]));
console.log(findMaxAndMin([1, 2, 3, 2, 0, -100, 1000]));
console.log(findMaxAndMin([1, 2, 3, 3, 3, 2, 1]));
console.log(findMaxAndMin([1,1,1,1,1,1,1,-100,-101,-1000,2,3,4,5,6,7,7,7,7,-10000]));
console.log(findMaxAndMin([1000,1,2,1,2,1,0,11000]));
console.log("use time = ", new Date().getTime() - timestart);
```
/** * 无序数组的样子就跟股票的走势一样,有一段上升,有一段下降,又有一段持平 * 那么我们每次比较时,只要在那些转折点进行比较即可 * 这样,如果这个无序数组这种上升或者下降趋势越长,比较次数减少的越多 * * @param {*} nums * @returns */ function findMaxAndMin(nums) { var max = nums[0], min = nums[0]; var count = 0; for (var i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]) { // 上升趋势 var j = i; while (nums[j] <= nums[j + 1]) { j++; } max = Math.max(max, nums[j]); i = j; } else { // 下降趋势 var j = i; while (nums[j] >= nums[j + 1]) { j++; } min = Math.min(min, nums[j]); i = j; } count++; } return { max, min, count }; } var timestart = new Date().getTime(); console.log(findMaxAndMin([1, 2, 3, 3, 4, 5, 5, 7])); console.log(findMaxAndMin([7, 6, 5])); console.log(findMaxAndMin([1, 2, 3, 2, 0, -100, 1000])); console.log(findMaxAndMin([1, 2, 3, 3, 3, 2, 1])); console.log(findMaxAndMin([1,1,1,1,1,1,1,-100,-101,-1000,2,3,4,5,6,7,7,7,7,-10000])); console.log(findMaxAndMin([1000,1,2,1,2,1,0,11000])); console.log("use time = ", new Date().getTime() - timestart);
是的,这种做法最坏的情况还是2N次比较.
你这里的count不是比较次数
是的,这种做法最坏的情况还是2N次比较
没有吧,最坏N次比较
var arr = [7, 2, 0, -3, 5, 9];
var max = Math.max.apply(null, arr);
var min = Math.min.apply(null, arr);
输出:
9 -3
var arr = [7, 2, 0, -3, 5, 9];
var max = Math.max.apply(null, arr);
var min = Math.min.apply(null, arr);
console.log(max, min);
输出:
9 -3
兄弟 你没有理解题
实际上只需要1.5N次比较,N是数组的长度
@azl397985856 先排序 然后直接取首尾行不行
@azl397985856 先排序 然后直接取首尾行不行
你算一下需要比较多少次
求一个无序数组中的最大值和最小值是一个很常见的情况, 一般来说, 最大值和最小值不是同一个元素, 我们可以通过下面几种方法来求:
方法3 和方法4的 过程很接近, 方法3 更为容易实现, 具体实现可见后续
// 找到数组元素的最大值和最小值
vector<int> findMinMax(vector<int> arr)
{
sort(arr.begin(),arr.end());
return {arr[0],arr.back()};
}
// 找到数组元素的最大值和最小值
vector<int> findMinMax(vector<int> arr)
{
int min_ = INT_MAX,max_ = INT_MIN;
for(int i=0;i<arr.size();++i)
{
if(arr[i] > max_)
max_ = arr[i];
if(arr[i] < min_)
min_ = arr[i];
}
return {min_,max_};
}
使用两个值记录最大值和最小值, 每次取出两个值,先进行比较,小的与最小值比较,大的与最大值比较 , 比较次数: $1.5*N$
// 找到数组元素的最大值和最小值
vector<int> findMinMax(vector<int> arr) {
int min_ = INT_MAX,max_ = INT_MIN;
// 处理前面偶数个元素
for(int i=0;i<arr.size()/2;++i) {
// 得到两个元素的最大值和最小值
int tmp_min,tmp_max;
if(arr[i] < arr[i+1]) {
tmp_min = arr[i];
tmp_max = arr[i+1];
} else {
tmp_min = arr[i+1];
tmp_max = arr[i];
}
// 比较,更新最大值和最小值
if(tmp_max > max_) max_ = tmp_max;
if(tmp_min < min_) min_ = tmp_min;
}
// 处理数组个数为奇数的情况 // 处理最后一个元素
if(arr.size()%2) {
int tmp = arr.back();
if(tmp > max_) max_ = tmp;
if(tmp < min_) min_ = tmp;
}
return {min_,max_};
}
比较前面偶数个元素,小的放在奇数位置,大的放在偶数位置, 比较次数: $1.5*N$
// 找到数组元素的最大值和最小值
vector<int> findMinMax(vector<int> arr) {
int min_ = INT_MAX,max_ = INT_MIN;
// 调整位置, 小的位于奇数,大的位置偶数
for(int i=0;i<arr.size()/2;i++) {
if(arr[i] > arr[i+1]) swap(arr[i],arr[i+1]);
}
// 更新最大值和最小值
for(int i=0;i<arr.size()/2;i++) {
if(arr[i] < min_) min_ = arr[i];
if(arr[i+1] > max_) max_ = arr[i+1];
}
// 处理数组个数为奇数的情况 // 处理最后一个元素
if(arr.size()%2) {
int tmp = arr.back();
if(tmp > max_) max_ = tmp;
if(tmp < min_) min_ = tmp;
}
return {min_,max_};
}
在N个数中求最小值Min和Max, 分成两个部分,依次取Min和Max,
略
@SChen1024 方便领取一下么
不知道怎么领取, 找了下 , 不知道怎么操作或者加入, 就直接回复了, 直接诶回复领取吗? 之后需要做什么呢?
@SChen1024 done 已经指派给你了 具体的认领步骤在这里: https://github.com/azl397985856/leetcode/tree/master/daily
Most helpful comment
无序数组中求最大值和最小值的最少比较次数
原理介绍
求一个无序数组中的最大值和最小值是一个很常见的情况, 一般来说, 最大值和最小值不是同一个元素, 我们可以通过下面几种方法来求:
方法3 和方法4的 过程很接近, 方法3 更为容易实现, 具体实现可见后续
算法实现
方法1 快排
方法 2
方法 3
使用两个值记录最大值和最小值, 每次取出两个值,先进行比较,小的与最小值比较,大的与最大值比较 , 比较次数: $1.5*N$
方法 4
比较前面偶数个元素,小的放在奇数位置,大的放在偶数位置, 比较次数: $1.5*N$
方法5
在N个数中求最小值Min和Max, 分成两个部分,依次取Min和Max,
略
参考链接