https://leetcode.com/problems/kth-largest-element-in-an-array/description/
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小的数字。这种题,用一个O(nlogn)的比较排序,然后直接取第k个 第(前)k大数问题 的总结。
我以前也转载过相关解法 求已知N个数中第k小的数。
这道题的解法是比较综合的。首先,递归分治,借鉴了快速排序的思路,将数组根据任意元素(这里取第一个)分成两半,a.如果从end到pivot正好k个,那么就是第pivot个元素。b.如果end到pivot>k个,递归处理pivot+1到end,取第k个。c.如果小于k个,则取前半段(start到pivot-1),取第k-(end - pivot+1)个。
其次,根据上面的表述,和binary search也很像吧。一不小心就会出现stack overflow的问题,开始我就写错了,注释掉了。因为在pivot==start的时候,start得不到更新,死循环了。
时间复杂度,因为上面的b和c每次只选择执行一次,而不是像快排,每次两个都要执行。所以时间复杂度为O(n)。
因为O(n+n/2+n/4...) = O(2n)。
public class Solution { public int findKthLargest(int[] nums, int k) { return find(nums, 0, nums.length - 1, k); } public int find(int[] nums, int start, int end, int k) { if(start > end) { return -1; } int pivot = partition(nums, start, end); if(end - pivot + 1 == k) { return nums[pivot]; } else if(end - pivot + 1 > k) { // return find(nums, pivot, end, k); return find(nums, pivot + 1, end, k); } else { return find(nums, start, pivot - 1, k - (end - pivot + 1)); } } public int partition(int[] nums, int start, int end) { if(start == end) { return start; } int pivot = start + 1; for(int i = start + 1; i <= end; i++) { if(nums[i] < nums[start]) { int temp = nums[pivot]; nums[pivot] = nums[i]; nums[i] = temp; pivot++; } } int temp = nums[pivot - 1]; nums[pivot - 1] = nums[start]; nums[start] = temp; return pivot - 1; } }
// 20181015
这里的partition用快排中的partition2更清晰
https://www.cnblogs.com/NickyYe/p/4645410.html
class Solution { public int findKthLargest(int[] nums, int k) { return find(nums, k, 0, nums.length - 1); } public int find(int[] nums, int k, int start, int end) { int pivot = partition(nums, start, end); if (k == end - pivot + 1) { return nums[pivot]; } else if (k < end - pivot + 1) { return find(nums, k, pivot + 1, end); } else { return find(nums, k - (end- pivot) - 1, start, pivot - 1); } } public int partition(int[] nums, int start, int end) { int pivot = nums[start], i = start, j = end; while (i < j) { while (i <= end && nums[i] <= pivot) { i++; } while (nums[j] > pivot) { j--; } if (i > j) { break; } int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } // j不可能<start,因为nums[start] == pivot int temp = nums[start]; nums[start] = nums[j]; nums[j] = temp; return j; } }