輸入整數數組 arr ,找出其中最小的 k 個數。例如,輸入4、5、1、6、2、7、3、8這8個數字,則最小的4個數字是1、2、3、4。
示例 1:
輸入:arr = [3,2,1], k = 2
輸出:[1,2] 或者 [2,1]
示例 2:
輸入:arr = [0,1,2,1], k = 1
輸出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
思路1:排序
需要最小的k個數,那麼只需要先排序,然後返回前k個數即可。
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
arr.sort()
return arr[:k]
思路2:堆
我們用一個大根堆實時維護數組的前 k小值。首先將前 k個數插入大根堆中,隨後從第 k+1個數開始遍歷,如果當前遍歷到的數比大根堆的堆頂的數要小,就把堆頂的數彈出,再插入當前遍歷到的數。最後將大根堆裏的數存入數組返回即可。在下面的代碼中,由於 C++ 語言中的堆(即優先隊列)爲大根堆,我們可以這麼做。而 Python 語言中的堆爲小根堆,因此我們要對數組中所有的數取其相反數,才能使用小根堆維護前 k 小值。
參考至Leetcode
這個數據全部取反,這個思路確實巧,直接將找k小變成了找k大,這樣就直接可以使用python中的heapq這個小根堆來做了,小根堆堆頂爲最小值,這樣我們每次和它比較,如果比他大就將其彈出,並將大的壓入。
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
if k == 0 or arr == []:
return []
hp = [-a for a in arr[:k]]
heapq.heapify(hp)
for i in range(k, len(arr)):
if -arr[i] > hp[0]:
# 先壓入,在彈出
heapq.heappushpop(hp, -arr[i])
return [-hp[i] for i in range(len(hp)-1, -1, -1)]
思路3:快排思想
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
if k == 0 or arr == []:
return []
def sort(left, right):
if left >= right:
return
l = left
r = right
key = arr[left]
# 進行一次排序:
while l < r:
while r > l and arr[r] >= key:
r -= 1
while l < r and arr[l] <= key:
l += 1
arr[l], arr[r] = arr[r], arr[l]
arr[l], arr[left] = arr[left], arr[l]
# 遞歸排序
if k == l or k == l + 1:
return
elif k < l + 1:
sort(left, l- 1) # 注意這裏上限是 l-1, 不是k-1
else:
sort(l + 1, right)
sort(0, len(arr)-1)
return arr[:k]