以盡量高的效率求乙個亂序陣列中第k小的元素
演算法1用快排先將陣列排序,然後直接找第k個元素,時間複雜度為o(nlgn)
演算法2思路用分割槽查詢的思想,同樣有點排序的感覺,畢竟分割槽就是將小於主元的元素放左邊,大於主元的元素放右邊。
與排序完再查詢不同的是:
對於一次遞迴呼叫來說:
比如原來陣列10個元素,假設主元為第4個元素,如果位置(不是下標)k為3,則下次劃分為前5個元素,它的位置還是3;
如果k為6,則下次劃分為的陣列為第5-10個元素,它的位置為6-4=2,即第2個位置
時間複雜度分析
最好情況
每次主元的選取都選中整個陣列的中值,由於每次分割槽後只在原來的一半進行查詢,所以如果找到最後才找到的話(即待查位置的元素每次都不是主元),那時間複雜度為o(lgn)
最差情況
如果每次主元都選中邊界前乙個的話(左邊n-1個元素,右邊1個),如果找到最後才找到的話(即待查位置的元素每次都不是主元),那要進行n(1+n)/2 次運算,時間複雜度為o(n^2)
平均情況
三點分割槽法選取的中值比較合理,如果找到最後才找到的話(即待查位置的元素每次都不是主元),時間複雜度也是o(lgn)
**
int selectk(int* arr,int begin, int end,int k)
其中的分割槽函式要用到之前快排的分割槽函式,這裡用雙向掃瞄分割槽法,主元的選取採用3點中值法
/*快速排序-雙向掃瞄分割槽分割槽法
功能:選取乙個主元,將小於主元的數放陣列左邊,大於主元的數放右邊
//三點中值法確定主元
*/int partition2(int* arr,int begin,int end)
else if(arr[begin]<=arr[end]&&arr[begin>=arr[mid]])
else if(arr[begin]<=arr[end]&&arr[begin]<=arr[mid])
else
}else if(arr[begin]>=arr[end]&&arr[begin]>=arr[mid])
else
}int left=begin+1;
int right=end;
while(left<=right)
}int tmp=arr[begin];//交換主元到右指標的位置
arr[begin]=arr[right];
arr[right]=tmp;
return right;
}
求亂序陣列中第K大的值
投機取巧用函式進行處理,沒有從演算法角度思考 編譯成功60 還得再想想哪些案例沒有實現 include include include using namespace std int main 輸入為首行亂序數列,第二行為k值 int num vectorv1 while cin num int k...
亂序陣列中第k大的數(順序統計量)
該問題是順序統計量中十分經典的問題。使用快排中的分割槽法,將第k大的數排序。若雙向掃瞄分割槽加上三點中值法或絕對中值法,可以保證在 o n 時間裡找出第k大的數。補充 可以直接使用c stl中的nth element函式 一定注意使用形式!1 2 第k大的數 3 4int part int arr,...
從乙個無序陣列中求出第K大 小的數
這個題目可以作為練習寫大 小根堆的實現,不過貌似時間複雜度還是蠻高的。在洛谷上面一道模板題上面好像就超時了幾個點,不知道是不是我實現的問題。那麼除此之外,最容易想到的方法是先對該陣列進行排序,然後取出第k或max k數來。當選擇使用快排的時候,時間複雜度是 o nlogn 但還有一種更優的方法是利用...