赞
踩
给定一个一维数组,同时找到最大最小的元素,并给出优化方法
思路:遍历一遍一维数组,一次比较确定最大值和最小值。
#include<stdio.h>
#include<assert.h>
void Search_Op(int arr[], int len, int *out_min, int *out_max)
{
assert(len > 0);//数组长度必然是大于0的
int min = arr[0];
int max = arr[0];
for (int i = 1; i < len; i++)
{
if (arr[i] < min)
{
min = arr[i];
}
if (arr[i] > max )
{
max = arr[i];
}
}
*out_min = min;//利用地址建立联系,改变函数外部的变量值
*out_max = max;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
size_t len = sizeof(arr) / sizeof(arr[0]);
int min = 0;
int max = 0;
Search_Op(arr, len, &min, &max);
printf("min=%d,max=%d", min, max);
return 0;
}
假设数组的长度为n,则该算法的时间复杂度为O(n),确定最大值的比较次数为n-1次,确定最小值的比较次数也为n-1次,总共比较次数为2(n-1)。
思路:最小值的取值范围肯定是小于等于最大值时,也就是
min<=max
。那我们可以考虑到如果解法一中判断arr[i] < min
成立的话,就会有arr[i] < min<=max
成立。此时,判断arr[i] > max
是不可能成立的,那么这种优化是不是可以减少n-1的比较次数呢?
void Search_Op1(int arr[], int len, int *out_min, int *out_max)
{
assert(len > 0);
int min = arr[0];
int max = arr[0];
for (int i = 1; i < len; i++)
{
if (arr[i] < min)
{
min = arr[i];
}
else if (arr[i] > max)
{
max = arr[i];
}
//else 相等情况
}
*out_min = min;
*out_max = max;
}
优化一最好的情况下,元素呈递减规律,只要执行第一个判断
if (arr[i] < min)
,比较n-1次;最坏的情况元素递增规律,和解法一比较次数相同。
思路:既然我们可以一个一个元素遍历处理,那我们也可以对一对元素进行遍历。
void Search_Op2(int arr[], int len, int *out_min, int *out_max)
{
assert(len > 0);
if (1 == len)//处理数组中只有一个元素的情况
{
*out_min = arr[0];
*out_max = arr[0];
return;
}
int max, min;
if (arr[0] < arr[1])//确定第一对的最大值和最小值
{
min = arr[0];
max = arr[1];
}
else
{
min = arr[1];
max = arr[0];
}
int i;
for (i = 2; i < len - 1; i += 2)//按对循环比较
{
if (arr[i] < arr[i + 1])
{
if (arr[i] < min)
{
min = arr[i];
}
if (arr[i + 1]>max)
{
max = arr[i + 1];
}
}
else
{
if (arr[i + 1] < min)
{
min = arr[i + 1];
}
if (arr[i] > max)
{
max = arr[i];
}
}
}
if (i != len)//如果是奇数,剩最后一个元素比较处理
{
if (arr[i] < min)
{
min = arr[i];
}
else if (arr[i] > max)
{
max = arr[i];
}
//else 相等情况
}
*out_min = min;
*out_max = max;
}
优化二分两种情况:数组长度为偶数或者是奇数。当为偶数时,首先比较两个相连的元素,然后把较小的与min比较,较大的与max比较,每一对元素需要3次比较,一共是3(n)/2次,当为奇数时,最后剩下一个元素可能需要比较一次也可能是两次,所以总的次数为3(n)+1/2或者3(n)+2/2。
思路:利用递归的方法大事化小,分三种情况处理:有一个元素时,有两个元素时,有三个或三个以上(分两块递归查找)
void Search_Op3_D(int arr[], int len, int *out_min, int *out_max)
{
assert(len > 0);
if (1 == len)//(1)递归结束条件
{
*out_min = arr[0];
*out_max = arr[0];
}
else if (len == 2)//(2)递归结束条件
{
if (arr[0] < arr[1])
{
*out_min = arr[0];
*out_max = arr[1];
}
else
{
*out_min = arr[1];
*out_max = arr[0];
}
}
else//(3)
{
int mid = len / 2;
int min1, max1, min2, max2;
//递归查找第一部分min和max
Search_Op3_D(arr, mid, &min1, &max1);
//递归查找第二部分min和max
Search_Op3_D(arr+mid, len-mid, &min2, &max2);
//确定最终的min和max
*out_min = min1 < min2 ? min1 : min2;
*out_max = max1 > max2 ? max1 : max2;
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。