Order statistics
After the array with length n is sorted in ascending order, the number at position i is the smallest quantity i of the array, which is called the ith order statistic
The minimum value of the array is the first order statistic, the maximum value is the nth order statistic, and the median (also known as the lower median) is the ⌊ (n+1)/2 ⌋ order statistic
⌊ n ⌋ means rounding down n and ⌈ n ⌉ means rounding up n
Maximum and minimum
If you want to find the maximum or minimum of N numbers, you only need to make (n-1) comparisons
int min = a[0]; for(int i=1;i<n;i++){ if(a[i] > min) min = a[i]; }
Obviously, this is the optimal algorithm. We call it "traversal search", because the algorithm simply traverses the entire array to find the maximum or minimum value. It requires a total of (n-1) comparisons, that is, S(n)=n-1
Now we want to study how to find the maximum and minimum values of the array at the same time with the lowest time complexity
traditional method
The easiest way to think of is to repeat the "traversal search" twice to find the maximum and minimum values respectively. Then S(n)=2(n-1) comparisons are required, but this is obviously not the best scheme.
Set the existing array a = [9,0,1,2100]
When looking for the minimum value, when traversing the second element, because 0 < 9, the minimum value is replaced with 0. At the same time, we can also know that 0 must not be the maximum value, because there is a 9 larger than it.
When looking for the maximum value, the same algorithm is adopted, resulting in 0 being compared again, and now 0 cannot be the maximum value.
optimization algorithm
Through the above traditional methods, we can find that the key to reducing the number of comparisons is to reduce unnecessary comparisons, which gives us an idea. Divide an array into k segments, find out the maximum and minimum values of the K numbers, and then compare them with the maximum and minimum values of the whole array
Suppose that the maximum and minimum values in the array with the search length of N need to be compared at most f(n) times, the array is divided into n/k segments, each segment has k numbers, and each segment needs to be compared f(k) times to obtain the maximum and minimum values, then a total of
![](/images/think/c884221b4ad27efa16295e4a9ae6aa58.jpg)
You can get n/k maximum value arrays and minimum value arrays at one time. When looking for the minimum value of the whole array, you only need to look for it from the minimum value array, and you need to compare it to find the maximum and minimum value of the whole array
![](/images/think/9d8059397fd641454f766138c72f55de.jpg)
Times, so we get the function of f(n)
![](/images/think/c13c5dd7071b47c394a54d317d9fcbfa.jpg)
Similarly, for the array with length k, we can divide it into smaller segments until k = 2, f(2)=1, because the two numbers only need to be compared once to get the maximum and minimum value. Let's assume that the array with length n is divided into segments with length k1, and the segments with length k(i-1) are divided into smaller segments with length ki, which are brought into f(n)
![](/images/think/6be0b14d544d989f703fc22f5be4c130.jpg)
Since kx must be a positive number, when i is 1, the continuous addition on the right disappears, and f(n) takes the minimum value, that is, k1=2
![](/images/think/f6122dff2099613dbd991c6f4c081af4.jpg)
The premise of obtaining the above results is that the initial values of min and max are defined in advance, but in practical application, we can dynamically adjust the initial values according to the array. If the length is even, first compare the first two items, the large one as max and the small one as min, for a total of (3n/2-1) times; If the length is odd, both min and max take the first term, so the actual comparison times should be (3n/2-2), that is, the final comparison times should be
![](/images/think/a0c50fb3c1d7975c095d0cfa34c42daa.jpg)
Through theory, we know that as long as the numbers in the array are compared in pairs, the smaller one is compared with the minimum value, while the larger one is compared with the maximum value, the maximum and minimum value can be obtained at the same time with the least number of comparisons
void FindMinAndMax(int* a, int len){ int min, max, i; if(len % 2 == 0){ //When the length is even, set the larger one between the first two items as the maximum value and the smaller one as the minimum value if(a[0] < a[1]){ min = a[0]; max = a[1]; }else{ min = a[1]; max = a[0]; } //Starting from a[2] and a[3], i is 3 i = 3; }else{ //When the length is cardinal, set the maximum and minimum values to a[0] min = max = a[0]; //Starting from a[1] and a[2], i is 2 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-th order statistics
If you want to find the ith order statistic in the array, that is, the number with the smallest i, the usual way is to sort the whole array and then directly take out the number at the corresponding position. Quick sort is a good way. Quick sort divides the array into two sub arrays to sort. In fact, we only care about the number of one position, so for the two sub arrays divided by quick sort, we only need to sort one of them
int find(int *a, int left, int right, int k) { if (left >= right) { return a[left]; } //key is the selected benchmark value int i = left, j = right, key = a[left]; while (i < j) { //Traverse the array to find the first number larger than key while (a[i] < key) { ++i; } //Traverse the array to find the first number smaller than key while (a[j] > key) { --j; } //Exchange. At this time, the smaller key is on the left and the larger key is on the right if (i < j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } } //At this time, the reference value is at the ith position of the whole array //s is the position of the reference value in the array starting with left, and i is the position of the reference value int s = i - left + 1; if (s == k) {//If s==k, it indicates that the benchmark value is the number to be searched, and the benchmark value is returned return a[i]; } else if (s > k) {//If s > k, it indicates that the reference value is on the right of the number to be searched, and the left array is traversed return find(a, left, j, k); } else {//If s < K, it means that the reference value is on the left of the number to be searched, then traverse the array on the right return find(a, j + 1, right, k - s); } }
The comparison times of this method are affected by random factors, so it is a random algorithm. On average, its time complexity can reach O(n)