劍指offer 面試題30 最小的K個數

2021-07-11 00:22:50 字數 1199 閱讀 5423

題目:輸入n個數,找出其中最小的k個數。例如輸入4、5、1、6、2、7、3、8這8個數字,則最小的4個數字是1,2,3,4。

思路:這道題目是典型的top k問題。兩種方法:

(1)如果允許改變量列,半快速排序,是基準值正好為第k個數,那麼基準值左邊的都是小於它的,即可得到最小的k個數(求最大的過程類似),時間複雜度o(n)。

(2)不允許改變量列,採用維護陣列的方法,建立乙個最大堆。遍歷數列,如果數字小於堆頂,那麼堆頂很明顯不是最小的k個數,更新堆頂,直到所有數字都已經與堆頂比較,堆上的數字即為最小的k個數。

半快速排序在面試題29裡講過,在此不再討論。見連線:

堆的實現可以用陣列,也可以利用stl裡的multiset容器,下面是分別用兩種實現過程的求解**:

1.用multiset實現

typedef multiset>    intset;

typedef multiset>::iterator setiterator;

void getleastnumbers(const vector& data, intset& leastnumbers, int k)}}

}

2.用陣列實現

如果陣列從0開始計數(也有從1開始),順序儲存堆的結點,那麼對於結點i,它的左右子結點和父親有這樣的關係:

左兒子:2*i+1

右兒子:2*i+2

父親:    (i-1)/2

建堆過程:上濾建堆。因為陣列總是在末尾插入新的元素,這時候比較它和父親的大小,比父親小則交換,逐步上移,直到大於父結點。

插入過程:和建堆過程類似,上濾法。

維護二叉堆的過程是每次和堆頂元素比較,此時需要採取的是下濾過程,因此這裡需要上濾和下濾兩個例程。

void swap(int& a, int& b)

void siftup(int* a, int n)

void siftdown(int* a, int n)

}

topk演算法:

void topk(int *a, int n, int k)  

}  for(int i = 0; i < k; ++i)  

cout << heap[i] << " ";  

cout << endl;  

delete heap;

}

劍指offer 面試題30 最小的k個數

題目描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4.題目分析 這道題最簡單的思路莫過於把n個整數排序,然後最前面的k個數就是最小的k個數,但是時間複雜度是o nlogn 我們應該想一想有沒有更快的方法。解法一 o n 的演...

劍指Offer 面試題30 最小的k個數

題目 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,思路 1 首先,使用快排中的思路 每進行一次快排,會確定乙個位置上的數字,使得該位置前的數字都小於該數字,而該位置後的數字都大於該數字。2 所以,要找最小的k個數,即某一次快...

《劍指offer》面試題30 最小的k 個數

劍指offer 面試題30 最小的k 個數 1.題目描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,2.解題思路 1。全排序。時間複雜度o nlogn 2。partiton思想 用快速排序,時間複雜度o n 3。最大堆 時...