題目:
輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。
思路分析
簡單思路:先快排,再取數;
基於「先整體排序,然後取前k個元素」的思路引申:需要的是前k小的數,沒必要捨近求遠把整個陣列都排好序。這樣一來,時間複雜度可以降到o(nlogk)。利用最大堆演算法,只不過在這裡稍稍將最大堆演算法變為最小堆演算法,**如下:# -*- coding:utf-8 -*-
class
solution
:def
getleastnumbers_solution
(self, tinput, k)
:# write code here
ifnot tinput:
return
if k >
len(tinput)
:return
output = self.quick_sort(tinput)
return output[
:k]def
quick_sort
(self, input_list):if
len(input_list)
<=1:
return input_list
less =
greater =
base = input_list.pop(
)for x in input_list:
if x > base:
else
:return self.quick_sort(less)
+[base]
+ self.quick_sort(greater)
這道題明顯是希望使用堆排序,這裡也重新對堆排序進行一次盤點,# -*- coding:utf-8 -*-
# 最大堆,o(nlogk)
defgetleastnumbers_solution
(self, tinput, k):if
len(tinput)
< k:
return
res =
for i in tinput:
-i)if
len(res)
-i)return
sorted
(list
(map
(lambda x:
-x, res)
))
思路:
我們可以先建立乙個大小為k的資料容器來儲存最小的k個數字,接下來我們每次從輸入的n個整數中的n個整數中讀入乙個數。如果容器中已有的數字少於k個,則直接把這次讀入的整數放入容器之中;如果容器已經有k個數字了,也就是容器滿了,此時我們不能再插入新的數字而只能替換已有的數字。找出這已有的k個數中的最大值,然後拿這次待插入的整數和最大值進行比較。如果待插入的值比當前已有的最大值小,則用這個數替換當前已有的最大值;如果待插入的值比當前已有的最大值還要大,那麼這個數不可能是最小的k個整數之一,於是我們可以拋棄這個整數。
因此當容器滿了之後,我們要做3件事情:
一是在k個整數中找到最大數;
二是有可能在這個容器中刪除最大數;
三是有可能要插入乙個新的數字。
如果用乙個二叉樹來實現這個資料容器,那麼我們在o(logk)時間內實現這三步操作。因此對於n個輸入數字而言,總的時間效率就是o(nlogk)。
c++ version:
對於上述**,我們還可以進一步優化,不是每次迴圈都需要重新排序的,只有在更新了容器的資料之後,才需要重新排序。class
solution
for(
int i =
0; i < input.
size()
; i++
)else
for(
int j = k -
1; j >
0; j--)if
(result[k-1]
> input[i])}
}return result;
}private
:void
headadjust
(vector<
int>
&input,
int parent,
int length)
if(temp >= input[child]
) input[parent]
= input[child]
;
parent = child;
child =
2* parent +1;
} input[parent]
= temp;}}
;
python version:class
solution
for(
int i =
0; i < input.
size()
; i++
)else
for(
int j = k -
1; j >
0; j--
) change =
false;}
if(result[k-1]
> input[i])}
}return result;
}private
:void
headadjust
(vector<
int>
&input,
int parent,
int length)
if(temp >= input[child]
) input[parent]
= input[child]
;
parent = child;
child =
2* parent +1;
} input[parent]
= temp;}}
;
**解釋:# -*- coding:utf-8 -*-
class
solution
:def
headadjust
(self, input_list, parent, length)
: temp = input_list[parent]
child =
2* parent +
1while child < length:
if child +
1< length and input_list[child]
< input_list[child+1]
: child +=
1if temp >= input_list[child]
:break
input_list[parent]
= input_list[child]
parent = child
child =
2* parent +
1 input_list[parent]
= temp
defgetleastnumbers_solution
(self, tinput, k)
:# write code here
res =
length =
len(tinput)
change =
true
if length <=
0or k <=
0or k > length:
return res
res = tinput[
:k]for i in
range
(k, length+1)
:if change ==
true
:for j in
range(0
, k//2)
[::-
1]: self.headadjust(res, j, k)
for j in
range(1
, k)[:
:-1]
: res[0]
, res[j]
= res[j]
, res[0]
self.headadjust(res,
0, j)
change =
false
if i != length and res[k-1]
> tinput[i]
: res[k-1]
= tinput[i]
change =
true
return res
劍指Offer (29)最小的k個數
題目描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4。實現如下 測試用例中給出的返回值是有序的。嘖嘖。找到序列中最小的k個數,利用set,對數字進行insert或erase 紅黑樹中查詢 插入 刪除操作都為 o logk 最...
劍指offer 29 最小的K個數
輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4。最簡單容易想到的就是先排序,然後輸出前k個數即可。但是這樣明顯時間複雜度比較高。也可以使用另外的方法,具體不再詳述。class solution for int i 0 i inp...
劍指Offer 29 最小的k個數
目錄 基礎補充 解法一 輸入陣列排序,然後取前k個 解法二 基於partition函式 解法三 最大堆 最小堆 3.1 時間複雜度o nlogn 空間複雜度o n 3.2 時間複雜度o nlogk 空間複雜度o k 解法四 紅黑樹 multiset集合 python排序實現 vector的使用方法 ...