劍指 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]

限制:

0 <= k <= arr.length <= 10000

0 <= arr[i] <= 10000

做題思路:其實做這道題,還是有點套模板的嫌疑,尤其是可以直接套快排的模板,先看答案之前,可以先學習一下左神的快排程式碼。

public class Code_04_QuickSort {
public static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
} public static void quickSort(int[] arr, int l, int r) {
if (l < r) {
//swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
int[] p = partition(arr, l, r);
quickSort(arr, l, p[0] - 1);
quickSort(arr, p[1] + 1, r);
}
} //設定了less,more作為左右兩個邊界,然後讓l來與more相互比較,然後再進行交換資料,並移動l或者more的位置
public static int[] partition(int[] arr, int l, int r) {
int less = l - 1;
int more = r;
while (l < more) {
if (arr[l] < arr[r]) {
swap(arr, ++less, l++);
} else if (arr[l] > arr[r]) {
swap(arr, --more, l);
} else {
l++;
}
}
swap(arr, more, r);
return new int[] { less + 1, more };
} //交換陣列的資料
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}

一、哨兵操作

class Solution1 {
/*
這是執行的哨兵的操作,設定一個基數,大於這個基數移動到右邊,小於這個相反即可
*/
public int[] getLeastNumbers(int[] arr, int k) {
quickSort(arr, 0, arr.length - 1);
return Arrays.copyOf(arr, k);
} private void quickSort(int[] arr, int l, int r) {
//當陣列長度為1時終止
if (l >= r) return;
int i = l, j = r;
//這裡是把arr[l]當做基數,然後和arr[i]和arr[j]做對比,和快排或者荷蘭國旗問題有點像,大於或者小於就--或者++
while (i < j) {
while (i < j && arr[j] >= arr[l]) j--;
while (i < j && arr[i] <= arr[l]) i++;
swap(arr, i, j);
}
swap(arr, i, l);
//這是遞迴左(右)執行左右兩邊的劃分
quickSort(arr, l, i - 1);
quickSort(arr, i + 1, r); } private void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}

二、快排

class Solution2 {
/*
這是一個快排的操作思路
*/
public int[] getLeastNumbers(int[] arr, int k) {
if (k >= arr.length) return arr;
return quickSort(arr, k, 0, arr.length - 1);
} private int[] quickSort(int[] arr, int k, int l, int r) {
int i = l, j = r;
while (i < j) {
while (i < j && arr[j] >= arr[l]) j--;
while (i < j && arr[i] <= arr[l]) i++;
swap(arr, i, j);
}
swap(arr, i, l);
/*
這裡
i > k 則遞迴 左邊的快排(左邊的陣列)
i < k 則遞迴 右邊的快排(右邊的陣列)
*/
if (i > k) return quickSort(arr, k, l, i - 1);
if (i < k) return quickSort(arr, k, i + 1, r);
return Arrays.copyOf(arr, k);
} private void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}