十一,先祝祖国母亲繁荣昌盛!
题目描述:在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例一:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例二:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
这虽然是一道力扣中等题,但在面试中却经常被考到,考点为快速排序。
若直接采用快排,则会发现超时,代码如下:
class Solution {
public int findKthLargest(int[] nums, int k) {
quickSort(nums, 0, nums.length-1);
return nums[nums.length - k];
}
public static void quickSort(int[] array, int left, int right){
if(left < right){
int index = partition(array, left, right);
quickSort(array, 0, index-1);
quickSort(array, index+1, right);
}
}
public static int partition(int[] array, int left, int right){
int temp = array[left];
while(left < right){
while(left < right && array[right] >= temp){
right--;
}
array[left] = array[right];
while(left < right && array[left] <= temp){
left++;
}
array[right] = array[left];
}
array[left] = temp;
return left;
}
}
改进的代码,基于快排的选择方法,是对快排的改进,时间复杂度为O(n)。
class Solution {
Random random = new Random();
public int findKthLargest(int[] nums, int k) {
return quickSelect(nums, 0, nums.length - 1, nums.length - k);
}
public int quickSelect(int[] a, int l, int r, int index) {
int q = randomPartition(a, l, r);
if (q == index) {
return a[q];
} else {
return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
}
}
public int randomPartition(int[] a, int l, int r) {
int i = random.nextInt(r - l + 1) + l;
swap(a, i, r);
return partition(a, l, r);
}
public int partition(int[] a, int l, int r) {
int x = a[r], i = l - 1;
for (int j = l; j < r; ++j) {
if (a[j] <= x) {
swap(a, ++i, j);
}
}
swap(a, i + 1, r);
return i + 1;
}
public void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}