面試題40. 最小的k個數
注意leetcode和牛客網的區別!!!! 返回值的類型不一致;
題目
輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。
思路1 — 直接調用排序算法!!!
Array.sort(int[] a);其實現也是快速排序~
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
// 注意 牛客網中該題是返回AyyayList類,leetcode中返回的是數組int[];
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if(k > input.length) {
return list; // 注意邊界,此題k大於數組長度時,返回空的ArrayList<Integer>
}else{
Arrays.sort(input);// O(nlogn);
for(int i = 0; i < k; i++){
list.add(input[i]);
}
return list;
}
}
}
Array.sort()使用注意:
若是基本類型,需要轉化爲對應的對象類型(如:int轉化爲Integer)Arrays.sort()可以排序基本對象類型,但是不可以使用基本數據類型。
Arrays.sort()默認的是升序排序,降序排序可採用Collection.sort()匿名內部類。
數組與list一樣,需要遍歷出來
思路2 — 優化 快速排序~~
- 空間複雜度 O(1),不需要額外空間。
- 時間複雜度:和快速排序類似。由於快速選擇只需要遞歸一邊的數組,時間複雜度小於快速排序,期望時間複雜度爲 O(n),最壞情況下的時間複雜度爲 O(n^2)
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
// 注意 牛客網中該題是返回AyyayList類,leetcode中返回的是數組int[];
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> li = new ArrayList<Integer>();
//哭暈系列!!! 注意邊界條件~~~~~
if(input.length == 0 || k > input.length || k == 0 || input == null ){
return li;
}else{
int[] sort = quickSelected(input, 0, input.length-1, k-1);
for(int i = 0; i < k; i++){
li.add(sort[i]);
}
return li;
}
}
public int[] quickSelected(int[] arr, int low, int high, int k){
int j = quickSort(arr, low, high);
// 只要切分位置剛好等於k,則切分位置左邊的就是滿足條件的最小的k個數
if(j == k){
return arr;
}
// 如果切分位置大於k值,代表需要減小左邊的切分區間,繼續從左邊找最小的k個數。
if(j > k){
return quickSelected(arr, low, j-1, k);
}
// 如果切分位置小於k,說明右邊還要繼續從小到大的排序。
return quickSelected(arr, j+1, high, k);
}
// 快排切分, 每次切分都把比基數大的放在基數的右邊,比基數小的放在技術左邊。返回基數的切分位置。
public int quickSort(int[] arr, int low, int high){
int key = arr[low];
int i = low;
int j = high;
while(i < j){
while(key <= arr[j] && i < j){
j--;
}
while(key >= arr[i] && i < j){
i++;
}
if(i < j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
arr[low] = arr[j];
arr[j] = key;
return j;
}
}
思路3 —大根堆~~
注意: 需要掌握queue數據結構, 以及PriorityQueue優先隊列(通過二叉小頂堆實現),優先隊列的作用是能保證每次取出的元素都是隊列中權值最小的(Java的優先隊列每次取最小元素,C++的優先隊列每次取最大元素)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Queue;
import java.util.PriorityQueue;
public class Solution {
// 注意 牛客網中該題是返回AyyayList類,leetcode中返回的是數組int[];
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> li = new ArrayList<Integer>();
if(input.length < k || k == 0){
return li;
}
Queue<Integer> heap = new PriorityQueue<>(k, (v1, v2) -> Integer.compare(v2, v1));
for(int num: input){
if(heap.isEmpty() || heap.size() < k || num < heap.peek()){
heap.offer(num);
}
if(heap.size() > k){
heap.poll();
}
}
for(int e: heap){
li.add(e);
}
return li;
}
}