将长度为n n n i i i i i i i i i 
数组最小值是第1个顺序统计量,最大值是第n n n ⌊ n + 1 2 ⌋ \left⌊\frac{n+1}{2}\right⌋ ⌊ 2 n + 1  ⌋ 
⌊ n ⌋ ⌊n⌋ ⌊ n ⌋ n n n ⌈ n ⌉ \left⌈n\right⌉ ⌈ n ⌉ n n n 
若想要寻找n n n ( n − 1 ) (n-1) ( n − 1 ) 
查找最小值 1 2 3 4 5 int  min = a[0 ];for (int  i=1 ;i<n;i++){    if (a[i] > min)         min = a[i]; } 
显然这已经是最优的算法了,我们称他为“遍历查找”,因为该算法是简单地遍历了整个数组来寻找最大或最小值,总共需要( n − 1 ) (n-1) ( n − 1 ) S ( n ) = n − 1 S(n)=n-1 S ( n ) = n − 1 
现在我们要研究如何以尽可能低的时间复杂度来同时求出数组的最大值和最小值
最容易想到的方法就是重复两次“遍历查找”,分别找出最大和最小值,那么就需要S ( n ) = 2 ( n − 1 ) S(n)=2(n-1) S ( n ) = 2 ( n − 1 ) 
设存在数组A = [ 9 , 0 , 1 , 2 , 100 ] A=[9,0,1,2,100] A = [ 9 , 0 , 1 , 2 , 1 0 0 ] 
在寻找最小值时,当遍历到第2个元素时,由于0<9,所以最小值被替换成0,同时我们也可以得知0一定不是最大值,因为有个9比它更大.
在寻找最大值时,采用了相同的算法,导致0又被比较了一遍,而现在0不可能是最大值.
通过上面的传统方法,我们可以发现减少比较次数的关键是减少不必要的比较,这就给我们一个思路,将一个数组划分为k k k k k k 
设查找长度为n n n f ( n ) f(n) f ( n ) n k \frac nk k n  k k k f ( k ) f(k) f ( k ) ⌈ n k ⌉ f ( k ) \left⌈\frac nk\right⌉f(k) ⌈ k n  ⌉ f ( k ) n k \frac nk k n  ⌈ n k ⌉ \left⌈\frac nk\right⌉ ⌈ k n  ⌉ f ( n ) f(n) f ( n ) 
f ( n ) = ⌈ n k ⌉ f ( k ) + 2 ⌈ n k ⌉ f(n)=\left⌈\frac nk\right⌉f(k)+2\left⌈\frac nk\right⌉ f ( n ) = ⌈ k n  ⌉ f ( k ) + 2 ⌈ k n  ⌉ 
同理对于长度为k的数组,我们又可以将其分为更小的段,一直分下去,直到k = 2 k = 2 k = 2 f ( 2 ) = 1 f(2)=1 f ( 2 ) = 1 n n n k ( i − 1 ) k(i-1) k ( i − 1 ) k i ki k i f ( n ) f(n) f ( n ) 
f ( n ) = ⌈ n k 1 ⌉ f ( k 1 ) + 2 ⌈ n k 1 ⌉ = ⌈ n k 1 ⌉ ⌈ k 1 k 2 ⌉ f ( k 2 ) + 2 ( ⌈ n k 1 ⌉ + ⌈ k 1 k 2 ⌉ ) = ⌈ n k 1 ⌉ f ( k i ) ∏ x = 2 i ⌈ k x − 1 k x ⌉ + 2 ( ⌈ n k 1 ⌉ + ∑ x = 2 i ⌈ k x − 1 k x ⌉ ) ≥ ⌈ n k 1 ⌉ f ( k i ) ∏ x = 2 i k x − 1 k x + 2 ( ⌈ n k 1 ⌉ + ⌈ ∑ x = 2 i k x − 1 k x ⌉ ) ≥ ⌈ n k 1 ⌉ + 2 ( ⌈ n k 1 ⌉ + ⌈ ∑ x = 2 i k x − 1 k x ⌉ ) = 3 ⌈ n k 1 ⌉ + 2 ⌈ ∑ x = 2 i k x − 1 k x ⌉ \begin{array}{ll} f(n)&=\left⌈\frac n{k_1}\right⌉f(k_1)+2\left⌈\frac n{k_1}\right⌉ \\\\ &=\left⌈\frac n{k_1}\right⌉\left⌈\frac{k_1}{k_2}\right⌉f(k_2)+2\left(\left⌈\frac n{k_1}\right⌉+\left⌈\frac{k_1}{k_2}\right⌉\right) \\\\ &=\left⌈\frac n{k_1}\right⌉f(k_i)\prod\limits_{x=2}^{i}\left⌈\frac{k_{x-1}}{k_x}\right⌉+2\left(\left⌈\frac{n}{k_1}\right⌉+\sum\limits_{x=2}^{i}\left⌈\frac{k_{x-1}}{k_x}\right⌉\right) \\\\ &\geq \left⌈\frac{n}{k_1}\right⌉f(k_i)\prod\limits_{x=2}^{i}\frac{k_{x-1}}{k_x}+2\left(\left⌈\frac{n}{k_1}\right⌉+\left⌈\sum\limits_{x=2}^{i}\frac{k_{x-1}}{k_x}\right⌉\right) \\\\ &\geq \left⌈\frac{n}{k_1}\right⌉+2\left(\left⌈\frac{n}{k_1}\right⌉+\left⌈\sum\limits_{x=2}^{i}\frac{k_{x-1}}{k_x}\right⌉\right) \\\\ &= 3\left⌈\frac{n}{k_1}\right⌉+2\left⌈\sum\limits_{x=2}^{i}\frac{k_{x-1}}{k_x}\right⌉ \end{array} f ( n )  = ⌈ k 1  n  ⌉ f ( k 1  ) + 2 ⌈ k 1  n  ⌉ = ⌈ k 1  n  ⌉ ⌈ k 2  k 1   ⌉ f ( k 2  ) + 2 ( ⌈ k 1  n  ⌉ + ⌈ k 2  k 1   ⌉ ) = ⌈ k 1  n  ⌉ f ( k i  ) x = 2 ∏ i  ⌈ k x  k x − 1   ⌉ + 2 ( ⌈ k 1  n  ⌉ + x = 2 ∑ i  ⌈ k x  k x − 1   ⌉ ) ≥ ⌈ k 1  n  ⌉ f ( k i  ) x = 2 ∏ i  k x  k x − 1   + 2 ( ⌈ k 1  n  ⌉ + ⌈ x = 2 ∑ i  k x  k x − 1   ⌉ ) ≥ ⌈ k 1  n  ⌉ + 2 ( ⌈ k 1  n  ⌉ + ⌈ x = 2 ∑ i  k x  k x − 1   ⌉ ) = 3 ⌈ k 1  n  ⌉ + 2 ⌈ x = 2 ∑ i  k x  k x − 1   ⌉  
由于k x kx k x i i i f ( n ) f(n) f ( n ) k 1 = 2 k_1=2 k 1  = 2 
f ( n ) m i n = f ( n ) ∣ i = 1 = 3 ⌈ n 2 ⌉ f(n)_{min}=f(n)|_{i=1}=3\left⌈\frac{n}{2}\right⌉ f ( n ) m i n  = f ( n ) ∣ i = 1  = 3 ⌈ 2 n  ⌉ 
得到上述结果的前提是事先定义好了m i n min m i n m a x max m a x m a x max m a x m i n min m i n ( 3 n 2 − 1 ) (\frac{3n}{2}-1) ( 2 3 n  − 1 ) ( 3 n 2 − 2 ) (\frac{3n}{2}-2) ( 2 3 n  − 2 ) 
f ( n ) = 3 ⌊ n 2 ⌋ f(n)=3\left⌊\frac{n}{2}\right⌋ f ( n ) = 3 ⌊ 2 n  ⌋ 
通过理论我们得知了只要把数组中的数两两比较,其中的较小者和最小值比较,而较大者和最大值比较,就可以实现用最少的比较次数同时求出最大最小值
查找最大最小值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void  FindMinAndMax (int * a, int  len)     int  min, max, i;     if (len % 2  == 0 ){                  if (a[0 ] < a[1 ]){             min = a[0 ];             max = a[1 ];         }else {             min = a[1 ];             max = a[0 ];         }                  i = 3 ;     }else {                  min = max = a[0 ];                  i = 2 ;     }     while  (i < len){         if (a[i-1 ] < a[i]){             if (a[i-1 ]<min) min = a[i-1 ];             if (a[i]>max) max = a[i];         }else {             if (a[i]<min) min = a[i];             if (a[i-1 ]>max) max = a[i-1 ];         }         i += 2 ;     }     cout << "min:"  << min << endl;     cout << "max:"  << max << endl; } 
如果想要找到数组里的第 i 顺序统计量,也就是第 i 小的数字,通常的办法是把整个数组排序,然后直接取出对应位置的数字.快速排序是一个很好的办法,快速排序将数组划分为两个子数组来排序.实际上,我们只关心其中某一个位置的数字,因此对于快速排序划分出来的两个子数组,我们仅需要排序其中一个就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 int  find (int  *a, int  left, int  right, int  k)      if  (left >= right) {         return  a[left];     }          int  i = left, j = right, key = a[left];     while  (i < j) {                  while  (a[i] < key) {             ++i;         }                  while  (a[j] > key) {             --j;         }                  if  (i < j) {             int  temp = a[i];             a[i] = a[j];             a[j] = temp;         }     }               int  s = i - left + 1 ;     if  (s == k) {         return  a[i];     } else  if  (s > k) {         return  find (a, left, j, k);     } else  {         return  find (a, j + 1 , right, k - s);     } } 
该方法的比较次数受到随机因素的影响,因此是一个随机算法.在平均情况下,它的时间复杂度能够达到O(n)