陣列 最小的k個數

2021-07-13 18:30:50 字數 1753 閱讀 2798

問題描述: 求陣列中的最小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 ...