Leetcode 劍指 Offer 40. 最小的k個數
輸入整數陣列 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]
方法一:最直接的思路,簡單題就要對應簡單做法。用sort函式對 arr 排序,再取其前 k 個數即可。先放C++程式碼,思路簡單易懂。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void print(vector<int> inputvector){
for(int i:inputvector){
cout<<i<<endl;
}
}
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
if(arr.empty() || k == 0) {return {};}
vector<int> res;
sort(arr.begin(), arr.end());
for(int i : arr) {
if(k <= 0) {break;}
res.push_back(i);
-- k;
}
return res;
}
};
int main()
{
vector<int> myvector{4,5,1,6,2,7,3,8};
Solution S;
print(S.getLeastNumbers(myvector,4));
system("pause");
return 0;
}
方法二:利用最大堆(priority_queue)。
- 先將 arr 的前 k 個數入堆,因為是最大堆,所以堆頂的數一定是最大的。
- 那麼我們再從 arr 的第 k + 1 個元素迭代起,凡是遇到比當前堆頂元素小的,就將該元素 push 入堆並 pop 掉堆頂元素。
- 注意,每次執行完第二步之後,堆會自動更新,以保證堆頂元素始終為堆中所有元素的最大值。
先放C++程式碼,思路清晰明瞭。
#include <iostream>
#include <vector>
#include<queue>
using namespace std;
void print(vector<int> inputvector){
for(int i:inputvector){
cout<<i<<endl;
}
}
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
if(arr.empty() || k == 0) {return {};}
vector<int> res(k);
priority_queue<int> max_heap;
for(int i = 0; i < k; ++i) {max_heap.push(arr[i]);} // 用 arr 的前 k 個數填充最大堆
for(int i = k; i < arr.size(); ++i) {
if(arr[i] < max_heap.top()){
max_heap.pop();
max_heap.push(arr[i]); // 迴圈更新最大堆
}
}
for(int i = 0; i < k; ++i) {
res[i] = max_heap.top(); // 填充 res
max_heap.pop();
}
return res;
}
};
int main()
{
vector<int> myvector{4,5,1,6,2,7,3,8};
Solution S;
print(S.getLeastNumbers(myvector,4));
system("pause");
return 0;
}
方法三:快速選擇——退化的快速排序。先放C++程式碼,思路清晰明瞭,註釋都已寫好在程式碼中。
#include <iostream>
#include <vector>
#include<queue>
using namespace std;
void print(vector<int> inputvector){
for(int i:inputvector){
cout<<i<<endl;
}
}
class Solution {
private:
vector<int> res;
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
if(arr.empty() || k == 0) {return {};}
return quickSelection(arr, 0, arr.size() - 1, k - 1); // 注意第 k 個數對應的下標是 k - 1
}
vector<int> quickSelection(vector<int>& arr, int left, int right, int index) {
// partition函式將一個區間內所有小於下標為 j 的數放在 j 左邊,大於下標為 j 的數放在 j 右邊
int j = partition(arr, left, right);
if(j == index) { // 若 j 剛好等於 k - 1,將 arr[0] 至 arr[j] 輸入 res
for(int i = 0; i < j + 1; ++i) {res.push_back(arr[i]);}
return res;
}
// 若 j 小於 k - 1,將區間變成 [j + 1, right];反之,區間變成 [left, j - 1]
return j < index ? quickSelection(arr, j + 1, right, index) : quickSelection(arr, left, j - 1, index);
}
int partition(vector<int>& arr, int left, int right) {
int value = arr[left];
int i = left, j = right + 1;
while(true) {
while(++ i <= right && arr[i] < value); // 找到從左往右第一個大於等於 value 的下標
while(-- j >= left && arr[j] > value); // 找到從右往左第一個小於等於 value 的下標
if(i >= j) {break;} // 如果找不到,說明已經排好序了,break
swap(arr[i], arr[j]); // 如果找到了,交換二者
}
swap(arr[left], arr[j]); // arr[j]是小於 value 的,這一步使得所有小於下標為 j 的數都在 j 左邊
return j;
}
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
};
int main()
{
vector<int> myvector{4,5,1,6,2,7,3,8};
Solution S;
print(S.getLeastNumbers(myvector,4));
system("pause");
return 0;
}
相關文章
- LeetCode題解:劍指 Offer 40. 最小的k個數,二叉堆,JavaScript,詳細註釋LeetCodeJavaScript
- 【劍指offer】把陣列排成最小的數陣列
- 劍指offer:旋轉陣列的最小數字陣列
- 劍指offer 旋轉陣列的最小數字陣列
- 劍指Offer-把陣列中的數排成一個最小的數陣列
- 劍指Offer-34-把陣列排成最小的數陣列
- 劍指offer——把陣列排成最小的數C++陣列C++
- 劍指offer-轉陣列的最小數字-php陣列PHP
- LeetCode|劍指 Offer 49.醜數LeetCode
- 【劍指offer】7.旋轉陣列的最小數字陣列
- 劍指 Offer 11. 旋轉陣列的最小數字陣列
- 【劍指 Offer】11. 旋轉陣列的最小數字陣列
- Leetcode劍指offer(八)LeetCode
- 力扣 - 劍指 Offer 45. 把陣列排成最小的數力扣陣列
- 【leetcode】劍指 Offer 16. 數值的整數次方LeetCode
- 【劍指offer】旋轉陣列的最小值陣列
- 劍指Offer 表示數值的字串字串
- 【劍指offer】字串轉整數字串
- 【劍指offer】二進位制中1的個數
- 劍指offer面試題15 連結串列中倒數第K個結點面試題
- (python版)《劍指Offer》JZ06:旋轉陣列的最小數字Python陣列
- 《劍指offer》:[54]表示數值的字串字串
- 《劍指offer》:[41]陣列中和為S的兩個數陣列
- Leetcode 劍指 Offer 03. 陣列中重複的數字LeetCode陣列
- 《劍指Offer》- 連續子陣列的最大和或最小和陣列
- 劍指Offer系列之「表示數值的字串」字串
- 《劍指offer》JAVA題解,LeetCode評測JavaLeetCode
- LeetCode-劍指Offer刷題記錄LeetCode
- LeetCode 劍指 Offer 05. 替換空格LeetCode
- 【劍指offer】字串的排列字串
- 劍指 Offer 15. 二進位制中1的個數
- 劍指offer面試題11 數值的整數次方面試題
- 【LeetCode刷題(簡單程度)】劍指 Offer 57. 和為s的兩個數字LeetCode
- 《Leetcode of December》劍指 Offer 67. 把字串轉換成整數LeetCode字串
- 【劍指offer】【2】字串的空格字串
- 【劍指offer】字串的組合字串
- leetcode *劍指 Offer 47. 禮物的最大價值LeetCode
- 《劍指offer》:[49]把字串轉化成整數字串