给定n个数据元素,找出其中的最大元和最小元。
简单直观的方法:一个一个地找,用n-1次比较来找出最大元,再用n-2次比较找出最小元,比较次数(基本运算)为2n-3次。
此题最蛋疼的是为什么会想到用分治法来解决,为什么会知道分治法时间复杂度稍好,常数小?所以正常人不会往这方面想。
当用分治法时,时间复杂度的数量级不变,但比较次数减少,具体计算、证明参见邓建明老师算法课件。
本算法直接二分,更好地方法是将数组长度,划分为2的幂次,如n = 42, 42 = 32 + 8 + 2,这样比直接二分比较次数少一些,不过还是同一数量级O(n)。
1.h: 给main函数提供find_max_min的声明
#ifndef X1_H
#define X1_H
void find_max_min(const int *a, const int n, int &min, int &max);
#endif1.cc:具体实现
#include <vector>
#include "1.h"
using std::vector;
static void find_max_min_core(const int *a, const int begin, const int end,
vector<int> &vmin, vector<int> &vmax);
void find_max_min(const int *a, const int n, int &min, int &max)
{
if (n < 0)
return;
if (n == 1)
{
min = max = a[0];
return;
}
else
{
vector<int> vmin;
vector<int> vmax;
find_max_min_core(a, 0, n-1, vmin, vmax);
vector<int>::iterator min_iter = vmin.begin();
// 声明临时变量比直接用min引用效率高,因为引用需要间接
// 访存,尤其在for循环中,效率更低
int temp_min = *min_iter;
for (; min_iter != vmin.end(); ++min_iter)
{
if (temp_min > *min_iter)
temp_min = *min_iter;
}
vector<int>::iterator max_iter = vmax.begin();
int temp_max = *max_iter;
for (; max_iter != vmax.end(); ++max_iter)
{
if (temp_max < *max_iter)
temp_max = *max_iter;
}
min = temp_min;
max = temp_max;
}
}
static void find_max_min_core(const int *a, const int begin, const int end,
vector<int> &vmin, vector<int> &vmax)
{
if (begin > end)
return;
if (begin == end)
{
vmin.push_back(a[begin]);
vmax.push_back(a[begin]);
return;
}
else if (begin + 1 == end)
{
a[begin] < a[end] ?
(vmin.push_back(a[begin]), vmax.push_back(a[end])) :
(vmin.push_back(a[end]), vmax.push_back(a[begin]));
return;
}
else
{
find_max_min_core(a, begin, begin + (end-begin)/2, vmin, vmax);
find_max_min_core(a, begin + (end-begin)/2 +1, end, vmin, vmax);
}
}main.cc:
#include <iostream>
#include "1.h"
using std::cout;
using std::endl;
using std::cin;
static void input(int *a, int n);
int main()
{
int num;
cout << "Input the count of array: ";
cin >> num;
if (num <=0 )
return 0;
int *pa = new int[num];
input(pa, num);
int min = 0, max = 0;
find_max_min(pa, num, min, max);
cout << "min: " << min << endl;
cout << "max: " << max << endl;
delete[] pa;
return 0;
}
static void input(int *a, int n)
{
cout << "Input " << n << " numbers:" << endl;
for (int i = 0; i < n; i++)
{
cin >> *(a+i);
}
}
makefile:
main: main.o 1.o
g++ -o main main.o 1.o
main.o: main.cc 1.h
1.o: 1.cc 1.h
clean:
rm -f *.o main运行结果:
xxl@xxl-pc:~/算法/分治法-求数组最大元和最小元$ ./main
Input the count of array: 2
Input 2 numbers:
1 2
min: 1
max: 2
xxl@xxl-pc:~/算法/分治法-求数组最大元和最小元$ ./main
Input the count of array: 1
Input 1 numbers:
4
min: 4
max: 4
该博客探讨如何运用分治法在给定的n个数据元素中寻找最大元和最小元。虽然简单方法需要2n-3次比较,但通过分治法,可以降低比较次数,尽管时间复杂度仍为O(n)。文章提到更优的策略是将数组长度划分为2的幂次,以进一步减少比较次数。博主分享了算法的实现代码,并提供了makefile。
2758

被折叠的 条评论
为什么被折叠?



