第k小数2
对于两个有序数组,要求取出第k小的数
首先对数组a[]和数组b[]取两者的中间位置idxA = a, lenth/2, idxB = b, lenth / 2,LenA为a数组前半段的个数,LenB为b数组前半段的个数。则分三种情况考虑:
(1)若LenA + LenB > k
a:A【idxA】 >= B[idexB],则舍弃A数组后半段
b:A【idxA】 <= B[idexB],则舍弃B数组后半段
(2)若LenA + lenB < k
a:A【idxA】 >= B[idexB],则舍弃A数组前半段
b:A【idxA】 <= B[idexB],则舍弃B数组后半段
(3)若LenA + LenB = k,表示答案已经找到。
1 /*对于两个有序数组,要求取出第k小的数*/ 2 3 #include<iostream> 4 #include<cstdlib> 5 #include<cstdio> 6 #include<algorithm> 7 using namespace std; 8 9 const int sup = 100010; 10 int A[sup], B[sup]; 11 12 bool myCMP(int a, int b) 13 { 14 return a < b; 15 } 16 17 int Bserach(int s1, int e1, int s2, int e2, int kth) 18 { 19 int idxA = (s1 + e1) >> 1;//一分为二 20 int idxB = (s2 + e2) >> 1; 21 int lenA =idxA - s1 + 1; 22 int lenB = idxB - s2 + 1; 23 if(s1 > e1) 24 lenA = 0; 25 if(s2 > e2) 26 lenB = 0; 27 int Len = lenA + lenB;//两个数组中当前取出的元素个数和 28 //超出了要求的k个元素,那么根据不同情况 29 //将两个数组中的一个截掉后半部分,保留前半部分 30 if(Len > kth) 31 { 32 //数组A为空或当前B中与中间元素更大,则K大数倾向于存在B的前半部分 33 if(0 != lenB && (0 == lenA || A[idxA] <= B[idxB]))//B中还有元素 34 return Bserach(s1, e1, s2, idxB - 1, kth);//截掉b数组中的一半元素 35 else 36 return Bserach(s1, idxA - 1, s2, e2, kth);//否则只能截取A中元素 37 } 38 else//两个数组中选取元素个数不够k个,那么根据不同情况 39 //将两个数组中的一个后移到后半部分 40 { 41 if(kth == Len) 42 { 43 if(0 == lenA) 44 return B[idxB]; 45 else if(0 == lenB) 46 return A[idxA]; 47 } 48 49 if(0 != lenA && (0 == lenB || A[idxA] <= B[idxB])) 50 return Bserach(idxA + 1, e1, s2, e2, kth - lenA); 51 else//已知道前lenA个大的元素,在剩下的元素中找到第kth - lenA大的数 52 return Bserach(s1, e1, idxB + 1, e2, kth - lenB); 53 } 54 } 55 56 int main() 57 { 58 int n, m, k; 59 cin >> n >> m >> k; 60 for(int i = 0; i < n; i++) 61 cin >> A[i]; 62 for(int i = 0; i < m; i++) 63 cin >> B[i]; 64 sort(A, A + n, myCMP); 65 sort(B, B + m, myCMP); 66 cout << Bserach(0, n - 1, 0, m - 1, k); 67 return 0; 68 }