215. 数组中的第K个最大元素 BFPRT最牛解法
【摘要】 在未排序的数组中找到第 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 ≤ 数组的长度。
思路:堆...
在未排序的数组中找到第 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();
-
}
-
*/
-
}
文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。
原文链接:fantianzuo.blog.csdn.net/article/details/104079514
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)