http://poj.org/problem?id=2388
問題是要從未經過排序的數組中找到中位元。很多人說這題是水題。其實此題不水。只不過測試的資料水了點。應該讓排序的代碼都逾時,就沒人說水題了。
這題的思想是用快排劃分的思想。即數組中以一個數字為分水嶺,如果大於該數的數字和小於該數的數字數量相等,則該數就是我們要求的中位元。這樣演算法的時間複雜度是O(n),最差為O(n^2),通過排序的話快排是O(n*lgn),通過小根堆對前一半的資料排序的話是O(n/2*lgn)。相比之下,快排劃分的演算法優缺點都可以看出來了。
當然隨著資料量的增加,當主存無法放下全部的資料的時候,這時應該選擇用小根堆排序。因為這時必然要用到外存,而外存的io速度。。。你懂得。
這時使用小根堆只需要掃描資料一遍。(聽說面試時,很多人問)
#include<stdio.h>#include<string.h>#include<iostream>void swap(int* arr, int x,int y){int temp = arr[x];arr[x] = arr[y];arr[y] = temp;}int partition(int* arr, int begin, int end){int i, j;i = begin;long pivot = arr[begin];for(j=begin+1; j<=end; j++)if(arr[j] <= pivot)swap(arr, ++i, j);swap(arr, i, begin);return i;}int select(int* arr, int begin, int end, int i){if(begin == end)return arr[begin];int p = partition(arr, begin, end);int k = p - begin + 1;if( k == i )return arr[p];else if(k < i)return select( arr, p+1, end, i - k);elsereturn select( arr, begin , p - 1, i);}int main(){int n;std::cin>>n;int q = 0;int* arr = new int[n];for(int i = 0; i < n; i++)std::cin>>arr[i];std::cout<<select(arr, 0, n - 1, (n + 1)/2 )<<std::endl;delete []arr;return 0;}