面試題40:最小的k個數
阿新 • • 發佈:2020-08-18
輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4。
解題思路
- 排序後遍歷(相當於簡化後的暴力)O(logn)
- 藉助快排的Partition思想O(n)
上程式碼(C++香)
法一:排序後遍歷(相當於簡化後的暴力)
class Solution { public: void mySwap(vector<int> &num, int i, int j){ int temp = num[j]; num[j] = num[i]; num[i] = temp; } int myPartition(vector<int> &num, int low, int high){ int pivot = num[low]; while(low < high){ // 將右邊比pivot小的放到左邊 while(low < high && num[high] >= pivot) high--; mySwap(num, low, high); while(low < high && num[low] <= pivot) low++; mySwap(num, low, high); } return low; } // 快排 void QSort(vector<int> &num, int low, int high){ if(low >= high) return ; int pivot = myPartition(num, low, high); QSort(num, low, pivot - 1); QSort(num, pivot + 1, high); } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> ans; if(k > input.size()) return ans; QSort(input, 0, input.size() - 1); for(int i = 0; i < k; i++) ans.push_back(input[i]); return ans; } };
法二:藉助快排的Partition思想
得到pivot如果與k-1相等,那麼陣列左邊的數已經就比num[k-1]小了,所以找到這個pivot就行。
void mySwap(vector<int> &num, int i, int j){ int temp = num[j]; num[j] = num[i]; num[i] = temp; } int myPartition(vector<int> &num, int low, int high){ int pivot = num[low]; while(low < high){ // 將右邊比pivot小的放到左邊 while(low < high && num[high] >= pivot) high--; mySwap(num, low, high); while(low < high && num[low] <= pivot) low++; mySwap(num, low, high); } return low; } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> ans; int length = input.size(); if(k > length) return ans; int low = 0; int high = length - 1; int pivot = myPartition(input, low, high); while(pivot != k - 1){ // k-1在左邊繼續找 if(pivot > k - 1){ high = pivot - 1; pivot = myPartition(input, low, high); } else{ low = pivot + 1; pivot = myPartition(input, low, high); } } for(int i = 0; i < k; i++) ans.push_back(input[i]); return ans; }