I. Question
Set X [1 .. n] and y [1 .. n] is two arrays, each containing N sorted numbers. An algorithm is provided to calculate the O (lgn) Time of the median of all 2n elements in array X and array y.
Ii. Ideas
Solve the problem recursively. The solution scale is halved. When there are four elements left, the solution is obtained,
This paper calculates the lower median, which is characterized:
(1) When n is an odd number, so n = 2 * m + 1, the lower median is the number smaller than m + 1, and the number of M in the array is smaller than the lower median, the number of M is greater than the lower median. When a number in the array meets any of the following characteristics, the number is considered not the lower median:. at least m + 1 is larger than x B. at least m + 1 is smaller than X
(2) When n is an even number, so n = 2 * m, the lower median is the number smaller than m + 1, and the number of M in the array is smaller than the lower median, the number of such instances is greater than the lower median. When a number in the array meets any of the following characteristics, it is considered that this number is not the lower median: A. At least m is larger than x B. At least m + 1 is smaller than X.
So that Na is the number of elements in array A, Nb is the number of elements in array B, Ma is the lower median in array A, and MB is the lower median in array B, A = Na/2, B = Nb/2. They meet the following requirements:
(1) Na and NB are equal at the beginning. After processing the array, they are still equal, and their parity is the same. Similarly, A and B are always equal.
(2) The size of Ma and MB is uncertain. This article illustrates the processing method of MA> MB.
The problem can be divided into the following two situations:
(1) both NA and NB are even numbers, so that Na = 2 * a, NB = 2 * B, A = B, Ma> MB (initial)
Analysis:
In array A There are a numbers less than Ma, there are A-1 numbers greater than Ma
In array B There are B numbers less than MB, there are B-1 numbers greater than MB
Ma> MB ====> all numbers greater than ma are larger than MB, and numbers smaller than MB are smaller than Ma
====> A and B have at least a + B + 1 digit less than Ma, at least a + b-1 number greater than MB
====> All numbers greater than Ma (excluding Ma) are not medians, and all numbers smaller than MB (excluding MB) are not medians.
======> A [1 .. na]-> A [1 .. A + 1], B [1 .. NB]-> B [B + 1 .. NB]
(2) Both Na and NB are even numbers, so that Na = 2 * A + 1, NB = 2 * B + 1, A = B, Ma> MB (initial condition)
Analysis:
In array a, a number is smaller than Ma, And a number is greater than Ma.
In array B, there are B numbers smaller than MB, and B Numbers greater than MB.
Ma> MB ====> all numbers greater than ma are larger than MB, and numbers smaller than MB are smaller than Ma
====> In A and B, at least a + B + 1 number is smaller than Ma, and at least a + B + 1 number is greater than MB.
====> All numbers greater than Ma (excluding Ma) are not medians, and all numbers smaller than MB (including MB) are not medians.
======> A [1 .. na]-> A [1 .. A + 1], B [1 .. NB]-> B [B + 1 .. NB]
After the above analysis, the final algorithm process is as follows:
Step 1: Calculate the values of the two arrays MIDA and midb respectively, and compare the sizes of MIDA and midb.
Step 2: If MIDA = midb, this value is the median in the number (Na + Nb ).
Step 3: If MIDA <midb, a [1 .. na]-> A [A + 1 .. na], B [1 .. NB]-> B [1 .. b] recursively calculate the median for two new arrays.
Step 4: If MIDA> midb, a [1 .. na]-> A [1 .. a], B [1 .. NB]-> B [B + 1 .. calculate the median of two new arrays recursively.
Step 5: Repeat the recursive operation in the Step1-Step4 until the remaining elements of the two arrays do not exceed 4, directly calculate the median for these 4 elements.
Iii. Code
// 9.3-8 # include <iostream> using namespace STD; void print (int * a, int S, int e) {int I; for (I = s; I <= E; I ++) cout <A [I] <''; cout <Endl ;} // In the worst case, the linear time has been selected many times. Int partition (int * a, int P, int R) is not interpreted) {int x = A [R], I = p-1, J; For (j = P; j <r; j ++) {if (a [J] <= X) {I ++; swap (A [I], a [J]) ;}} swap (A [I + 1], a [R]); return I + 1;} int select (int * a, int P, int R, int I); // sort the insertion of each group from start to end, the returned value // The insertion sorting is very simple. Int insert (int * a, int start, int end, int K) {int I, j; for (I = 2; I <= end; I ++) {int T = A [I]; for (j = I; j> = start; j --) {If (j = start) A [J] = T; else if (a [J-1]> T) A [J] = A [J-1]; else {A [J] = T; break ;}}return A [start + k-1];} // according to the algorithm in this paper, find the median int find (int * a, int P, int R) {int I, j = 0; int start, end, Len = r-p + 1; int * B = new int [Len/5 + 1]; // a group of five elements with the length from start to end. insert and sort each group and return the median for (I = 1; I <= Len; I ++) {if (I % 5 = 1) Start = I + p-1; if (I % 5 = 0 | I = Len) {J ++; end = I + p-1; // sort the inserts from start to end in each group, and return the median value. If it is the last group, the number of elements in the group may be less than 5int ret = insert (a, start, end, (end-Start)/2 + 1 ); // pick out the values in each group to form a new array B [J] = RET ;}// recursively call select () int ret = select (B, 1, J, (J + 1)/2); // Delete [] B; return ret ;} // F-based division int partition2 (int * a, int P, int R, int f) {int I; // locate the position of F and make it exchange with a [R] for (I = P; I <r; I ++) {if (a [I] = f) {swap (A [I], a [R]); break ;}} return partition (A, P, R) ;}// search for Array a [p .. the largest I element in R]. I is counted from 1, not from P. Int select (int * a, int P, int R, int I) {// If the array contains only one element, if (P = r) return a [p]; // based on the algorithm in the text, find the median int F = find (A, P, R); // use this median as the primary element, and return the median value in the entire array a [1 .. len] position // because the principal component is an element in the array, the Division is like this. A [p .. q-1] <= F <A [q + 1 .. r] int q = partition2 (A, P, R, f); // convert the value to the value in array a [p .. r] In the position int K = Q-p + 1; // compare with the searched element if (I = k) return a [Q]; else if (I <k) return select (A, P, Q-1, I); else // if the principal element is an element in the array, the latter half should write return select (, q + 1, R, I-k); // if the principal element is not an element in the array, change the latter half to select (A, Q, R, i-k + 1)} int selectmid (int * a, int start, int end) {return select (A, start, end, (end-start + 1) /2 + 1);} // returns the second small number of ABCD, which has been a <B, c <dint getret (int A, int B, int C, int D) {if (a <c) {If (C <B) Return min (B, d); Return C;} else {if (a <D) return min (B, d); return a ;}}// algorithm process int solve (int * a, int * B, int N) {int ret; int starta = 1, startb = 1, enda = N, endb = N; while (1) {If (ENDA = starta) return max (A [starta], B [startb]); // if there are only four elements left, return the 2nd Small element of the four elements if (Enda-starta = 1) {ret = getret (A [starta], A [ENDA], B [startb], B [endb]); break;} // obtain the values in A and B, respectively, here we will handle the case that A and B are not sorted // If A and B are sorted, only mid = A [(start + end) /2] You can obtain the value int MIDA = selectmid (A, starta, Enda); int midb = selectmid (B, startb, endb ); // cout <MIDA <''<midb <Endl; // print (A, starta, Enda); // print (B, startb, endb ); // The select algorithm contains the division process, so you can cut off the first half of array A and the last half of array B directly. // remove the First Half of array, make sure that the number of AB array elements after removal is equal if (MIDA = midb) {ret = MIDA; break;} // remove the first half of a and the second half of array B, note that the elements in the last two arrays are equal to else if (MIDA <midb) {starta = starta + (Enda-starta + 1)/2; endb = endb-(endb-startb + 1)/2;} // remove the First Half of B and the second half of array, note that the elements in the last two arrays are equal to else {ENDA = Enda-(Enda-starta + 1)/2; startb = startb + (endb-startb + 1)/2 ;} // print (A, starta, Enda); // print (B, startb, endb);} return ret;} // test the algorithm process int main () {int N, i; while (CIN> N) {int * A = new int [n + 1]; int * B = new int [n + 1]; // generate random data for (I = 1; I <= N; I ++) {A [I] = rand () % 100; B [I] = rand () % 100;} // print the generated data print (A, 1, n); print (B, 1, n); // algorithm process int ret = solve (, b, n); // output result cout <RET <Endl; delete a; Delete B;} return 0 ;}
Iv. Test