215. 数组中的第K个最大元素
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2 输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
第一次交换,算法复杂度为O(N),接下来的过程和快速排序不同,快速排序是要继续处理两边的数据,(可以这么理解,每次交换用了N,一共logN次)。但是这里在确定枢纽元的相对位置(在K的左边或者右边)之后不用再对剩下的一半进行处理。也就是说第二次插入的算法复杂度不再是O(N)而是O(N/2),这不还是一样吗?其实不一样,因为接下来的过程是1+1/2+1/4+........ < 2,
换句话说就是一共是O(2N)的算法复杂度也就是O(N)的算法复杂度
class Solution {
public int findKthLargest(int[] nums, int k) {
int index = nums.length - k;
int l = 0;
int r = nums.length - 1;
while(l <= r) {
int rand = (int)(Math.random() * (r - l + 1) + l);
swap(nums, rand, r);
// 标准数的左右边界
int[] idxs = partition(nums, l, r);
if(index > idxs[1]) {
l = idxs[1] + 1;
} else if(index < idxs[0]) {
r = idxs[0] - 1;
} else {// index >= idxs[0] && index <= idxs[1]
return nums[idxs[0]];
}
}
return -1;
}
// 分为三部分
public int[] partition(int[] nums, int l, int r) {
int less = l - 1; // 小于等于区域的右边界
int more = r; // 大于区域的左边界
while(l < more) {
if(nums[l] < nums[r]) {
swap(nums, ++less, l++);
} else if(nums[l] > nums[r]) {
swap(nums, --more, l);
} else {
l++;
}
}
swap(nums, more, r);
return new int[]{less+1, more};
}
public void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}