問題描述: 求陣列中的最小k個數。
分析:
<1>使用線性選擇演算法來快速實現(o(n)),具體來說就是借助快速排序的思想,把陣列分為比主元v小的部分s1,和比主元v大的部分s2。
1.若k <= |s1|,則第k小的元素在s1,就遞迴的對s1進行相同的操作。
2.若k = |s1| + 1,那就表示主元就是第k小的元素,那就結束演算法,此時陣列的前k個元素就是要找的最小k個元素。
3.若k > |s1| + 1,則第k小的元素在s2中,那就遞迴的對s2進行相同操作。
4.若陣列太短,就直接使用插入排序即可。
void quickselect(int arr, int k, int
left, int
right)
if(left
<= right - 3)
swap(arr[i], arr[index]);
if(k <= i)
quickselect(arr, k, left, i - 1);
else
if(k > i + 1)
quickselect(arr, k, i + 1, right);
}else
insertsort(arr, left, right);
}void sortfirstmidlast(int arr, int first, int
mid, int
end)
void insertsort(int arr, int
left, int
right)
arr[local] = tmp;
}}
<2> 上述方法需要改變原來的陣列,若要使得原來陣列不變,則可以使用乙個大小為k的最大堆,先取陣列前k個數入堆並排序,然後從陣列的k+1個元素開始,每次與堆頂元素p進行比較,若arr[k+1] >= p,則繼續比較下乙個元素。若k[k+1] < p,則刪除堆頂元素,並將arr[k+1]插入堆中並將堆排序,然後繼續比較arr[k+2]…(此方法不會改變原始陣列,並且適合處理海量資料。其時間複雜度為o(nlogk)。//實現時,可以用乙個長為k的陣列來實現乙個最大堆)
void sortbyheap(int *arr, int *heap, int len)
for(int i = 0; i < n; i++) //將陣列前n個元素放入堆中
heap[i] = arr[i];
for(int
index = n/2; index >= 0; index--) //堆排序
for(int i = n; i < len; i++) //從第n+1個元素開始一一對比}}
}void heaprebuild(int rootindex, int *arr, int
count) //建立大頂堆
if(arr[rootindex] < arr[largerchildindex])
}}
<3> 使用基於紅黑樹的multiset來實現。
typedef
multiset
> intset;
typedef
multiset
>::iterator setiterator;
void getleastnumbers(const
vector
& data, intset& leastnumbers, int k)else}}
}
查詢陣列中最小k個數
思路 可採用大頂堆來實現 維護乙個規模為k的大頂堆。從前往後掃瞄陣列元素 若大頂堆的size小於k,則把當前元素插入大頂堆中 若小於k,若當前元素小於堆頂元素,則刪除堆頂元素,插入當前元素。考慮到從頭實現乙個大頂堆比較麻煩,這裡使用treeset容器,它提供有序的set。treeset底層實際使用的...
找出陣列中最小的k個數
leetcode 面試題40.最小的k個數 快速排序,時間複雜度為nlogn,然後前k個元素就是最小的k個數 class solution 原理也是快速排序的原理,只不過增加了停止條件。不用完全排序而已。class solution int label quicksort arr,0,arr.len...
最小的K個數
問題描述 給定的n個整數,計算其中最小的k個數。最直觀的解法莫過於將n個數按公升序排列後輸出前k個。但是就效率來看,這種方法並不是最理想的。一種改進方法是借助快速排序中對陣列的劃分,以第k個元素對陣列進行劃分,使得比第k個數字小的數字都在其左邊,比其大的數字都在它的右邊。void swap int ...