TopK算法看前三种。
基于快排的TopK算法:
快速排序使用了分治法的策略。它的基本思想是,选择一个基准数(一般称之为枢纽元),通过一趟排序将要排序的数据分割成独立的两部分:在枢纽元左边的所有元素都不比它大,右边所有元素都比它大,此时枢纽元就处在它应该在的正确位置上了。
在本问题中,假设有N个数存储在数组a中。我们从a中随机找出一个元素作为枢纽元,把数组分为两部分。其中左边元素都不比枢纽元大,右边元素都不比枢纽元小。此时枢纽元所在的位置记为mid。
如果右半边(包括a[mid])的长度恰好为k,说明a[mid]就是需要的第k大元素,直接返回a[mid]。
如果右半边(包括a[mid])的长度大于k,说明要寻找的第k大元素就在右半边,往右半边寻找。
如果右半边(包括a[mid])的长度小于k,说明要寻找的第k大元素就在左半边,往左半边寻找。
package com.test;
public class QuickSort {
public static void main(String[] args) {
int nums[] = {1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8, 9};
int result = findMaxK(nums, 0, nums.length - 1, 3);
System.out.println(result);
}
// TopK解法之快速排序
public static int QuickSort(int[] nums, int low, int high) {
// // 随机选一个元素作为枢纽元素
// // 左边都是比枢纽元素小的,右边都是比枢纽元素大的
// Random random = new Random();
// // 生成指定范围为[low, high]的随机数
// int idx = random.nextInt(high - low + 1) + low;
// // 将枢纽元素换到low的位置,接下来的代码就和快排的代码一样了
// 不取随机数了,就去low下标的元素
int temp = nums[low];
while (low < high) {
while (low < high && nums[high] >= temp) high--;
if (low < high) {
nums[low++] = nums[high];
}
while (low < high && nums[low] < temp) low++;
if (low < high) {
nums[high--] = nums[low];
}
}
nums[low] = temp;
return low;
}
public static int findMaxK(int[] nums, int low, int high, int k) {
int mid = QuickSort(nums, low, high);
int length_of_right = high - mid + 1;
if (length_of_right == k) return nums[mid];
else if (length_of_right < k) {
return findMaxK(nums, low, mid - 1, k);
} else {
return findMaxK(nums, mid + 1, high, k);
}
}
}