本章如果要归结成一个问题的话,可以归结为选择问题,比如要从一堆数中选择最大的数,或最小的数,或第几小/大的数等, 这样的问题看似很简单,似乎没有什么可研究的必要,因为我们已经知道了排序算法,运用排序+索引的方式不就轻松搞定了?但细想,排序所带来的时间复杂度是不是让这个问题无形之中变得糟糕。那算法研究不就是要尽可能避免一个问题高复杂度地解决,让那些不敢肯定有无最优解的问题变得不再怀疑,这也是算法研究者所追求的一种极致哲学。既然排序让这个问题解决的性能无法确定,那我们就抛开排序,独立研究问题本身,看有没有确定性的,且更优的解决之道,所以,这就是本章所探讨的问题。

一、中位数和顺序统计量

中位数:用非形式化的语言描述:中位数表示这样的一位数,它所属集合的“中点元素”。如果集合元素n为奇数,则中位数为(n+1)/2处;如果n为偶数,则中位数出现在n/2(下中位数)和n/2+1(上中位数)处,一般无特殊说明,我们都取下中位数。

顺序统计量:在一个n个元素组成的集合中,第i个顺序统计量是该集合中第i小的元素。

最大值:第1个顺序统计量。

最小值:第n个顺序统计量。

选择问题:给定一个包含n个元素的集合A和一个整数i,1<=i<=n,我们需要得到一个整数x,其中有i-1个元素小于它,即第i个顺序统计量。

前面说过,这个问题最直观的解法是通过排序+索引的方式,但排序算法有多种,且时间复杂度略高。我们需要更低时间复杂度来解决这个问题,要求线性时间,即O(n)。我们总结下算法导论上提出的方法,一步步展示如何O(n)来解决这个问题。

二、最大值、最小值

1、O(n)求最大值、最小值

  这个采用最直观朴素的解法就能解决,我们取个名字吧,叫做“锦标赛法”。就是一个个比较,时间复杂度O(n),已经没有比这更优的了。代码如下:

 1 /***********线性时间求最小值************/
 2 int Minimun(int arr[], int n)
 3 {
 4     int nMin = arr[0];
 5     for(int i = 1; i < n; i++)
 6         //min
 7         if(nMin > arr[i])
 8             nMin = arr[i];
 9         //max
10 //         if (nMax < arr[i])
11 //             nMax = arr[i];
12     return nMin;
13 }

2、3/2n次比较同时求最大最小值

  按照锦标赛法,同时求最大最小值,需要2(n-1)次比较,但是换一种思路,我们没必要一个元素比较两次,而是两个元素比较一次,然后得出大小关系,在分别和最大、最小值比较,这样两个元素就只用比较3次,总共就是3/2n次。这里要分奇偶数看待,但不管奇偶,都需要3/2n次。比较次数减少了,时间也就降低了。代码如下:

 1 /***********通过3n/2次比较求最小值和最大值**********/
 2 void MinAndMax(int arr[], int n, int &nMin, int &nMax)
 3 {
 4     int i;
 5     //如果n是奇数
 6     if(n % 2 == 1)
 7     {
 8         //将最大值和最小值设置为第一个元素
 9         nMin = arr[1];
10         nMax = arr[1];
11         i = 2;
12     }
13     //如果n是偶数
14     else
15     {
16         //将前两个元素作一次比较,以决定最大值怀最小值的初值
17         nMin = min(arr[1], arr[2]);
18         nMax = arr[1] + arr[2] - nMin;
19         i = 3;
20     }
21     //成对地处理余下的元素
22     for(; i < n; i=i+2)
23     {
24         //将一对输入元素互相比较
25         int a = min(arr[i], arr[i+1]);
26         int b = arr[i] + arr[i+1] - a;
27         //把较小者与当前最小值比较
28         if(a < nMin)
29             nMin = a;
30         //把较大者与当前最大值比较
31         if(b > nMax)
32             nMax = b;
33     }
34 }
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-10-09
  • 2021-06-29
  • 2022-12-23
  • 2021-06-24
  • 2021-08-13
  • 2022-12-23
猜你喜欢
  • 2021-09-17
  • 2021-10-17
  • 2021-10-20
  • 2021-10-05
  • 2022-12-23
  • 2021-06-03
  • 2022-03-11
相关资源
相似解决方案