在未排序的數組中找到第 k 個最大的元素。請注意,你需要找的是數組排序后的第 k 個最大的元素,而不是第 k 個不同的元素。
示例 1:
輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5
示例?2:
輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4
說明:
你可以假設 k 總是有效的,且 1 ≤ k ≤ 數組的長度。
思路:堆、改進快排、BFPRT
解釋鏈接
public class Solution {/*
//前k小public static int[] getMinKNumsByBFPRT(int[] arr, int k) {if (k < 1 || k > arr.length) {return arr;}int minKth = findKthLargest(arr, k);int[] res = new int[k];int index = 0;for (int i = 0; i != arr.length; i++) {if (arr[i] < minKth) {res[index++] = arr[i];}}for (; index != res.length; index++) {res[index] = minKth;}return res;}*/
//第k小public static int findKthLargest(int[] arr, int K) {int[] copyArr = copyArray(arr);return select(copyArr, 0, copyArr.length - 1, arr.length-K);}public static int[] copyArray(int[] arr) {int[] res = new int[arr.length];for (int i = 0; i != res.length; i++) {res[i] = arr[i];}return res;}
//給定一個數組和范圍,求第i小的數public static int select(int[] arr, int begin, int end, int i) {if (begin == end) {return arr[begin];}int pivot = medianOfMedians(arr, begin, end);//劃分值int[] pivotRange = partition(arr, begin, end, pivot);if (i >= pivotRange[0] && i <= pivotRange[1]) {return arr[i];} else if (i < pivotRange[0]) {return select(arr, begin, pivotRange[0] - 1, i);} else {return select(arr, pivotRange[1] + 1, end, i);}}
//在begin end范圍內進行操作public static int medianOfMedians(int[] arr, int begin, int end) {int num = end - begin + 1;int offset = num % 5 == 0 ? 0 : 1;//最后一組的情況int[] mArr = new int[num / 5 + offset];//中位數組成的數組for (int i = 0; i < mArr.length; i++) {int beginI = begin + i * 5;int endI = beginI + 4;mArr[i] = getMedian(arr, beginI, Math.min(end, endI));}return select(mArr, 0, mArr.length - 1, mArr.length / 2);//只不過i等于長度一半,用來求中位數}
//經典partition過程public static int[] partition(int[] arr, int begin, int end, int pivotValue) {int small = begin - 1;int cur = begin;int big = end + 1;while (cur != big) {if (arr[cur] < pivotValue) {swap(arr, ++small, cur++);} else if (arr[cur] > pivotValue) {swap(arr, cur, --big);} else {cur++;}}int[] range = new int[2];range[0] = small + 1;range[1] = big - 1;return range;}
//五個數排序,返回中位數public static int getMedian(int[] arr, int begin, int end) {insertionSort(arr, begin, end);int sum = end + begin;int mid = (sum / 2) + (sum % 2);return arr[mid];}
//手寫排序public static void insertionSort(int[] arr, int begin, int end) {for (int i = begin + 1; i != end + 1; i++) {for (int j = i; j != begin; j--) {if (arr[j - 1] > arr[j]) {swap(arr, j - 1, j);} else {break;}}}}
//交換值public static void swap(int[] arr, int index1, int index2) {int tmp = arr[index1];arr[index1] = arr[index2];arr[index2] = tmp;}/*
//打印public static void printArray(int[] arr) {for (int i = 0; i != arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}*/
}
?