如题:如何在乱序数组中寻找最大值和最小值,要求比较次数尽可能小。
思路:如果是单纯的遍历一边,会对每一个元素与存储的最大值和最小值进行比较,比较次数为2n,考虑到如果比最大的元素大,也就不用跟最小的元素进行对比了,比较次数会略小于2n。
显然这种思路过于常规,一般面试官也不会希望得到这种答案。
正确的思路是类似于快速排序的分组方式,对数组从两头进行分组,即第0个元素与第n-1个元素进行对比,大的放a组,小的放b组;然后第一个与n-2进行对比........直到两边序号重合,比较次数为n/2,这时,最大的数肯定在a组里,最小的数肯定在b组。然后再在a组里寻找最大值,再在b组里寻找最小值,分别都是n/2次比较,一共使用3/2n次比较就搞定啦。
上代码:
void findMaxandMinNumber(int nums[], int count) {
//分组
int i = 0;
for (; i < (count - i - 1); i++) {
if (nums[i]<nums[count-1-i]) {
//交换位置
int tem = nums[i];
nums[i] = nums[count-i-1];
nums[count-i-1] = tem;
}
}
int sep = 0;
int middle = 0;
if (i == count-i-1) {
//奇数
sep = count/2+1;
middle = nums[count/2];
} else {
//偶数
sep = count/2;
}
//大的一组
int max = nums[0];
for (int j=1; j<count/2-1; j++) {
if (nums[j]>max) {
max = nums[j];
}
}
//小的一组
int min = nums[sep];
for (int j=sep+1; j<count-1; j++) {
if (nums[j]<min) {
min = nums[j];
}
}
//与middle进行对比
if (i == count-i-1) {
if (middle>max) {
max = middle;
}
if (middle<min) {
min = middle;
}
}
printf("max = %d, min = %d", max, min);
}