In real life, we often encounter this kind of problem: in a collection, who is the biggest element? Who is the smallest element? Or who is the second-small element? Wait a minute. So how to solve this kind of problem in a short time, is the article to elaborate.
Get acquainted with several concepts first:
1. Sequential statistics:
In a set of n elements, the I ordinal statistic (order statistic) is the small element in the set. The minimum value is the 1th ordinal statistic (I=1), and the maximum value is the nth ordinal statistic (i=n).
2 . Median:
A median is the "midpoint element" of the collection to which it belongs, and when n is odd, the median is unique, at i= (n+1)/2, and when n is even, there are two median digits at I=N/2 and i=n/2+1 respectively.
first, maximum minimum value problem
Visually, for a set of n elements, how many comparisons are required to require the smallest element? It's easy to think, at least, to do a n-1 comparison; we only need to iterate through the collection to compare, and each time we record a smaller element, we get the smallest element at the end of the loop. You can also do this for the maximum value.
If the problem is to find the maximum and minimum value at the same time, of course, you can do two traversal, do a n-1 comparison, you can get the maximum value and the minimum value. However, this is not optimal because we do not need to compare each number to the maximum and the minimum value.
Take a collection of an even number of elements as an example, we can compare the first two elements, the big one first set to Max, and the small one first set to Min, and then the element because it is an even number, so split into two groups, first in the group to make a comparison, and then the group within the big to max, if larger than Max, The value of Max is replaced, otherwise it does not change, and the small within the group is compared to Min, and similar operations are done until the entire meta-collection is traversed. Then the total number of comparisons are: 1+ (n/2-1) *3=3n/2-2 times. If it is a collection of odd elements, omit the first comparison operation, then set Max and Min directly to the first element, followed by the same number of even cases. So for the set of odd elements, the total number of comparisons to be made is: ((n-1)/2) * 3 times. If you do not consider an odd or even number, we need at most 3[N/2] (maximum integer not greater than N/2) to get the maximum and minimum, or the time complexity of the algorithm is O (n).
The implementation of the code is also relatively simple:
#include <iostream>typedef int t;using namespace std;/* * Contains the result of the structure body, containing the maximum and minimum value */struct result {public:t max; T Min;result (): Max (0), min (0) {}};result* getminmax (int a[], int len), int main () {T a[9] = {5, 8, 0,-89, 9, 22,-1,-31 , 98};result* r1 = Getminmax (A, 9); cout << "Maximum value:" << r1->max << "minimum:" << r1->min <&L T Endl T b[10] = {5, 8, 0, -89, 9,,-1, -31, 98, 2222};result* r2 = Getminmax (b); cout << "Maximum:" << r2->m Ax << ", Minimum:" << r2->min << endl;delete r1;delete r1;return 0;} result* Getminmax (T a[], int len) {result* re = new result (); if (len = = 0) {return 0;} if (len = = 1) {Re->max = A[0];re->min = A[0];return Re;} if (len = = 2) {Re->max = a[0] > a[1]? a[0]: A[1];re->min = A[0] < a[1]? A[0]: A[1];return re;} int max, Min;int i = 0;if (len% 2 = = 0) {//The number of elements is even if the case Re->max = A[i] > a[i + 1]? A[i]: A[i + 1];re->min = a[i] < A[i + 1]? A[i]: a[i + 1];i + = 2;} Else{//The number of elements is odd Re->max = A[i];re->min = a[i];i++;} while (I < len) {//Compare values in paired numbers, and then compare with Max and min respectively max = A[i] > a[i + 1]? A[i]: A[i + 1];min = A[i] < A[i + 1]? a[ I]: a[i + 1];i + = 2;re->max = Re->max > Max? Re->max:max;re->min = re->min < min? Re->min:min;} return re;}
second, to find a set of the small element I, also known as the first I-CIS statistics
It looks as if it is much more complicated than asking for the maximum and minimum values, and in fact, a small element in the set of an element of reciprocity, the time complexity is the same as above, and O (n). The following is a quick ordering of the knowledge, you can see: one of the algorithm introduction (Quick Sort)
The idea here is similar to the quick sort, with quick sorting to find an mid position, continue to quickly sort the arrays on both sides of the mid. This is because you only need to find the position of the I-CIS statistic, so this element is either in the mid position or in an array on the left side of the mid, or in an array on the right side of the mid, so you just need to think about it. In contrast to the algorithm complexity, the desired time complexity of the fast ordering is O (NLGN), and here is O (n).
Specific ideas:
1, using the rapid sorting of the group , but a little improvement, each time the key value is no longer a definite position value, but first from all the elements of a random selection as the key value, and then to the end of the element exchange. The benefit is the ability to effectively avoid a state where each grouping is extremely unbalanced: 0:n-1. (from a probabilistic perspective, a random key value makes it possible for the worst case to occur every time there is no fixed situation).
2, after getting the random grouping result, we first look at the mid position of the element and we are looking for the first level of the statistic is not a position , if it is, then directly return to the mid position element. If you find that the mid position is before the I-CIS statistic, then we just need to recursively do the above for the part of the grouping, and conversely, if the mid is found to be in the first half of the I-level statistics, then we simply need to do the above-mentioned collection of recursive heap groupings.
The code is as follows:
/** * intended to solve: the linear time within O (n) to complete the search array in the small element i-*/#include <iostream>typedef int t;using namespace STD; T Randomizedselect (t a[], int start, int end, int i), int randomizedpartition (t a[], int start, int end); int Partitionarray (t a[], int start, int end), void Swap (t* A, t* b), void PrintArray (t* a, int len), void Randomizedquicksort (T a[], int start int main () {T a[10] = {1, 999, -1025, 654, 185, 5,-9,, 8,};cout << "array before sorting:";//<< Endl; PrintArray (A, ten); int pos = 3;cout << "<< pos <<" small element: "<< randomizedselect (A, 0, 9, POS) < ;< Endl;randomizedquicksort (A, 0, 9); cout << "Array after sorting:"; << Endl;printarray (A, ten); return 0;} /* * Find the first I cis statistic is the small element */t Randomizedselect (T a[], int start, int end, int i) {if (start = = end) {return a[start];} int q = randomizedpartition (A, start, end); int keypos = Q-start + 1; Find this element is the number of small elements, convenient with the first small element comparison//And I compared if (Keypos = = i) {return a[q];} else if (Keypos > i) {return randomizedselect (A, StArt, q-1, i);} else {//keypos<i return randomizedselect (A, q + 1, end, I-keypos);}} /* * Random grouping */int randomizedpartition (T a[], int start, int end) {int mid = rand ()% (End-start + 1) + Start;swap (A + end, A + mid); return Partitionarray (A, start, end);} /* Random Quick sort */void randomizedquicksort (T a[], int start, int end) {if (Start < end) {int k = randomizedpartition (A, STA RT, end); Randomizedquicksort (A, start, k-1); Randomizedquicksort (A, k + 1, end);}} /* * Normal grouping */int Partitionarray (T a[], int start, int end) {int i = start-1;int j = Start;//int p = start;int q = end; T key = A[end];while (J < Q) {if (A[j] >= key) {j++;continue;} else {I++;swap (a + I, A + j); J + +;}} I++;swap (A + I, A + j); return I;} /* * Swap two elements */void swap (t* A, t* b) {T tmp = *a;*a = *B;*B = tmp;} /* * Print array */void printArray (t* A, int len) {for (int i = 0; i < len; i++) {cout << a[i] << ';} cout << Endl;}
For the above algorithm why the time complexity is O (n) when the elements are different, in the "Introduction to the algorithm-third edition" p121~p122 page has detailed mathematical proof, here will not repeat. We can simply understand that for fast ordering, the expected time complexity is O (NLGN), its recursion after the grouping of the two sides of the two sets are recursive, and for the selection algorithm, only one side of the set to recursion, the speed is better than the fast row, in the case of mutual differentiation of elements, the time complexity of O (n )。
Introduction to the Algorithm VII (selection algorithm of median and sequential statistics)