問題:找出數組中第K大的數(類似:找出一個數組中個數超過一半的數,就是找第n/2(n爲數組長度)大的數)
解法思路:
設數組A[0,1.....n-1]
1、隨機選擇數組中的一個數,將該數與A[n-1]交換
2、遍歷數組,遇到比A[n-1]小的就依次放在數組的最前面(遍歷到第一個比A[n-1]小的放在A[0],第二個比A[n-1]小的放在A[1]....)
3、遍歷完(一遍),即可找到隨機選取的數是第幾大的。
以上三步代碼實現:
//返回i,是值p[i]是數組中第i+1大的數
int random_partition(int *p, int n){
int i = -1,j=0;
int idx = rand() % n;
swap(p[idx], p[n - 1]);
for (j = 0; j < n; j++){
if (p[j] < p[n - 1]){
swap(p[++i],p[j]);
}
}
swap(p[++i], p[n - 1]);
return i;
}
4、已經找到第i+1大的數 ,剩下的就是拿i+1跟k比較
int getMaxK(int *p, int n, int k){
int midx;
if (k <= 0 || k > n)
return -1;
midx = random_partition(p,n);
if (midx + 1 == k)
return p[midx];
else if (midx + 1>k)
return getMaxK(p, midx + 1, k);
else if (midx + 1 < k)
return getMaxK(p+midx+1,n-midx-1,k-midx-1);
}
測試:
<pre name="code" class="cpp"><pre name="code" class="cpp">void main(){
//找數組中個數大於一半的數
int a[11] = {1,2,3,2,3,3,5,3,7,3,3};
printArr(a,11);
cout << findVal(a, 11) << endl;
cout << getMaxK(a, 11, 11 / 2) << endl;
//找數組中第K大的數
/* int num, a[] = { 12012, 3, 945, 965, 66, 232, 65, 7, 8, 898, 56, 878, 170, 13, 5 };
cout << getMaxK(a, 15, 2) << endl;
cout << getMaxK(a, 15, 15) << endl;
cout << getMaxK(a, 15, 14) << endl;
*/
}