1 class Solution { 2 public: 3 /** 4 * @param nums: A list of integers. 5 * @return: An integer denotes the middle number of the array. 6 */ 7 void swap(vector<int> &v, int i, int j) 8 { 9 int tmp = v[i]; 10 v[i] = v[j]; 11 v[j] = tmp; 12 } 13 int getMinK(vector<int> &v, int left, int right, int k) 14 { 15 if(left<right) 16 { 17 int i = left-1, j = left; 18 for(; j<right; ++j) 19 { 20 if(v[j]<v[right]) 21 { 22 ++i; 23 swap(v, i, j); 24 } 25 } 26 swap(v, i+1, right); 27 if(k==i+1) return v[i+1]; 28 else if(k<=i) return getMinK(v, left, i, k); 29 else return getMinK(v, i+2, right, k); 30 } 31 else return v[left]; 32 } 33 int median(vector<int> &v) { 34 // write your code here 35 return getMinK(v, 0, v.size()-1, (v.size()-1)/2); 36 } 37 };
主要利用快排遞歸划分的思想,可以在期望復雜度為O(n)的條件下求第k大數。快排的期望復雜度為O(nlogn),因為快排會遞歸處理划分的兩邊,而求第k大數則只需要處理划分的一邊,其期望復雜度將是O(n)。詳細的證明見《算法導論》。
我們可以這樣粗略的思考:
假設我們的數據足夠的隨機,每次划分都在數據序列的中間位置,那么第一次划分我們需要遍歷約n個數,第二次需要遍歷約n/2個數,...,這樣遞歸下去,最后:n+n/2+n/(2^2)+n/(2^3)+...+n/(2^k)+... = (1+1/2+1/(2^2)+1/(2^3)+...+1/(2^k)+...)*n, 當k趨於無窮大的時候,上式的極限為2n。