leetcode解题之215. Kth Largest Element in an Array java 版(第k大的数字)

来源:互联网 发布:开淘宝的心得体会 编辑:程序博客网 时间:2024/06/05 23:41

215. Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.

查找数组第k大的数字

从一个未经排序的数组中找出第k大的元素。注意是排序之后的第k大,而非第k个不重复的元素可以假设k一定是有效的, 1 ≤ k ≤ 数组长度。O(n)解法:快速选择(QuickSelect)

public class Solution {public int findKthLargest(int[] nums, int k) {if (k < 1 || nums == null || nums.length < k) {throw new IllegalArgumentException();}return findKthLargest(nums, 0, nums.length - 1, k);}public int findKthLargest(int[] nums, int start, int end, int k) {// 中枢值int pivot = nums[start];int lo = start;int hi = end;while (lo < hi) {// 将小于中枢值的数移动到数组左边while (lo < hi && nums[hi] >= pivot) {hi--;}nums[lo] = nums[hi];// 将大于中枢值的数移动到数组右边while (lo < hi && nums[lo] <= pivot) {lo++;}nums[hi] = nums[lo];}nums[lo] = pivot;// 如果已经找到了if (end - lo + 1 == k) {return pivot;}// 第k大的数在lo位置的右边else if (end - lo + 1 > k) {return findKthLargest(nums, lo + 1, end, k);}// 第k大的数在lo位置的左边else {// k-(end-lo+1)// (end-lo+1):表示从lo位置开始到end位置的元素个数,就是舍掉右半部分// 原来的第k大变成k-(end-lo+1)大return findKthLargest(nums, start, lo - 1, k - (end - lo + 1));}}

使用最小堆

我们可以使用最小堆解决这个问题,有k个元素,当size大于k 的时候,删除,复杂度是O(nlog(k)).空间复杂度是O(k),

public int findKthLargest(int[] nums, int k) {    PriorityQueue<Integer> q = new PriorityQueue<Integer>(k);    for(int i: nums){        q.offer(i);         if(q.size()>k){            q.poll();        }    }     return q.peek();}

同样的思想查找中位数;

中位数:

快速排序

partition

// 查找第k大的数字public static int findKthLargest(int[] nums, int k) {int len = nums.length;int lo = 0;int hi = len - 1;int index = partition(nums, len, lo, hi);while (index != len - k) {if (index > len - k) {hi = index - 1;index = partition(nums, len, lo, hi);} else {lo = index + 1;index = partition(nums, len, lo, hi);}}return nums[lo];}// 查找中位数,无序,有重复public static double findMidle(int[] nums) {int len = nums.length;int lo = 0;int hi = len - 1;int mid = len / 2;int index = partition(nums, len, lo, hi);while (index != mid) {if (index > mid) {hi = index - 1;index = partition(nums, len, lo, hi);} else {lo = index + 1;index = partition(nums, len, lo, hi);}}System.out.println(Arrays.toString(nums));System.out.println(mid);if (len % 2 == 1)return nums[lo];elsereturn (nums[lo] + nums[lo - 1]) / 2.0;}// 快速排序public static void quickSort(int[] nums, int lo, int hi) {if (lo < hi) {int pivotPos = partition(nums, nums.length, lo, hi);quickSort(nums, lo, pivotPos - 1);quickSort(nums, pivotPos + 1, hi);}}// 基于快排的partitionpublic static int partition(int[] nums, int len, int lo, int hi) {// 中枢值int pivot = nums[lo];while (lo < hi) {// 将小于中枢值的数移动到数组左边while (lo < hi && nums[hi] >= pivot)hi--;nums[lo] = nums[hi];// 将大于中枢值的数移动到数组右边while (lo < hi && nums[lo] <= pivot)lo++;nums[hi] = nums[lo];}// 枢轴元素存放的位置nums[lo] = pivot;// 返回枢轴的最终位置return lo;}




0 0