TopK (MinK) 实现
Posted dqwangi33
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TopK (MinK) 实现相关的知识,希望对你有一定的参考价值。
概述:基于快排原理找到最小的K个元素,属于Top K问题。注意,使用快排原理找前K小问题不需要对整个数组进行O(nlogn)的排序。我们只要找K所在的区间进行递归调用,即每次只要对数据的一半进行递归调用,而不用对全部的数据进行递归调用,从而降低了时间复杂度。平均情况下,时间复杂度计算:n + n/2 + ... + n/n = 2n, 因此时间复杂度是O(n)。
1 import java.util.Arrays; 2 public class MinK { 3 public static void main(String[] args) { 4 int[] arr = {3,45,78,64,52,64,64,55,55,11,2}; 5 System.out.println(arrayToString(arr,"Array:")); 6 int k = 3; 7 int[] res = quickSearch(arr, 0, arr.length-1, k); 8 System.out.println(arrayToString(res,"MinK :")); 9 } 10 /** 11 * 基于快排找到最小的K个元素 12 * nums 数组 13 * left 数组左下标 14 * right 数组右下标 15 * k k值 16 */ 17 18 19 private static int[] quickSearch(int[] nums, int left, int right, int k) { 20 // 每快排切分1次,找到排序后下标为j的元素,如果j恰好等于k就返回j以及j左边所有的数; 21 int j = partition(nums, left, right); 22 if (j == k) { 23 return Arrays.copyOf(nums, j); 24 } 25 else if (j < k) { 26 return quickSearch(nums,j+1, right, k); 27 } 28 else{ 29 return quickSearch(nums, left, j-1, k); 30 } 31 } 32 33 // 快排切分,返回下标j,使得比numss[j]小的数都在j的左边,比numss[j]大的数都在j的右边。 34 private static int partition(int[] nums, int left, int right) { 35 int key = nums[left]; 36 int i = left; 37 int j = right; 38 while(i<j){ //当i=j时退出总循环 39 while(nums[j] >= key && i < j) j--; //从右往左,找到比key小的值方可退出循环 40 while(nums[i] <= key && i < j) i++; //从左往右,找到比key大的值方可退出循环 41 if(i<j){ 42 int temp = nums[i]; // 把左边大的值与右边小的值进行交换 43 nums[i] = nums[j]; 44 nums[j] = temp; 45 } 46 } 47 nums[left] = nums[i]; 48 nums[i] = key; //把key交换到中间 49 return i; 50 } 51 private static String arrayToString(int[] arr,String flag) { 52 String str = flag+‘ ‘; 53 for(int a : arr) { 54 str += a + " "; 55 } 56 return str; 57 } 58 59 }
结果:
以上是关于TopK (MinK) 实现的主要内容,如果未能解决你的问题,请参考以下文章
找出数组中第k大的数(时间复杂度分析C++代码实现). TopK in array. ( leetcode - 215 )
找出数组中第k大的数(时间复杂度分析C++代码实现). TopK in array. ( leetcode - 215 )
数据结构 设计一个算法,删除递增有序链表中值大于mink且小于maxk的所有元素(mink和maxk是给定的两个参数,其值 可以和表中的元素相同,也可以不同)