Problem: 215. 数组中的第K个最大元素
思路
💖 三路划分
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( log n ) O(\log{n}) O(logn)
class Solution {
public int findKthLargest(int[] nums, int k)
{
List<Integer> list = new ArrayList<>();
for (int x : nums)
list.add(x);
return quickSelect(list, k);
}
private int quickSelect(List<Integer> nums, int k)
{
Random rand = new Random();
int pivot = nums.get(rand.nextInt(nums.size()));
List<Integer> big = new ArrayList<>();
List<Integer> equal = new ArrayList<>();
List<Integer> small = new ArrayList<>();
for (int x : nums)
{
if (x < pivot)
small.add(x);
else if (x == pivot)
equal.add(x);
else
big.add(x);
}
if (k <= big.size())// 第 k 大在 big中
return quickSelect(big, k);
else if (big.size() + equal.size() < k)// 第 k 大在 small中
return quickSelect(small, k - big.size() - equal.size());
return pivot;// 当前选到的值就是第 k 大
}
}
💖 快速选择
class Solution {
int[] nums;
int qselect(int l,int r,int k){
if(l == r)//表示数组的所有元素都已经处理到最后一层了
return nums[k];
int x = nums[l];//保存标准值(此时取左边的元素为标准值)
int i = l;
int j = r;
while(i < j){
//先找右边不符合条件的放在左边(左边第一个值已经保存在 x 中了)
while(i < j && nums[j] >= x)
j--;
nums[i] = nums[j];
//再找左边不符合条件的放在右边
while(i < j && nums[i] <= x)
i++;
nums[j] = nums[i];
}
// 此时 i==j 为划分点
nums[j] = x;//最后的中间位置放标准值
if(k <= j) // 答案在左区间
return qselect(l,j,k);
else // 答案在右区间
return qselect(j+1,r,k);
}
void swap(int l,int r)
{
nums[l] ^= nums[r];
nums[r] ^= nums[l];
nums[l] ^= nums[r];
// int c = nums[l];
// nums[l] = nums[r];
// nums[r] = c;
}
public int findKthLargest(int[] nums1, int k) {
nums = nums1;
int n = nums.length;
return qselect(0,n-1,n-k);
}
}