1. 题⽬链接:215.数组中的第K个最⼤元素
2. 题⽬描述:
3. 解法(快速选择算法):
算法思路:
在快排中,当我们把数组「分成三块」之后: [l, left] [left + 1, right - 1] [right, r] ,我们可以通过计算每⼀个区间内元素的「个数」,进⽽推断出我们要找的元素是 在「哪⼀个区间」⾥⾯。
那么我们可以直接去「相应的区间」去寻找最终结果就好了。
C++算法代码:
class Solution
{
public:
int k_w=0; //第k个最大元素
//快速选择排序
int qsort(vector<int>& nums, int l, int r)
{
if(l==r)
{
return nums[l];
}
//选择关键字
int key = nums[rand()% (r - l + 1) + l];
int left = l - 1, right = r + 1, i = l;
//三区域划分
while (i < right)
{
if (nums[i] > key)
{
swap(nums[i], nums[--right]);
}
else if (nums[i] < key)
{
swap(nums[i++], nums[++left]);
}
else
{
i++;
}
}
//判断答案所在位置
//三区域范围大小
int a = left - l + 1, b = right - left - 1, c = r - right + 1;
if (c >= k_w)
{
return qsort(nums, right, r);
}
else if (b + c >= k_w)
{
return key;
}
else
{
k_w=k_w-b-c;
return qsort(nums, l, left);
}
}
int findKthLargest(vector<int>& nums, int k)
{
k_w = k;
//随机数种子
srand(time(NULL));
return qsort(nums, 0, nums.size() - 1);
}
};
Java算法代码:
class Solution
{
public int findKthLargest(int[] nums, int k)
{
return qsort(nums, 0, nums.length - 1, k);
}
public int qsort(int[] nums, int l, int r, int k)
{
if (l == r)
{
return nums[l];
}
// 1. 按照随机选择的基准元素,将数组分三块
int key = nums[new Random().nextInt(r - l + 1) + l];
int left = l - 1, right = r + 1, i = l;
while (i < right)
{
if (nums[i] < key) swap(nums, ++left, i++);
else if (nums[i] == key) i++;
else swap(nums, --right, i);
}
// 2. 分情况讨论
int c = r - right + 1, b = right - left - 1;
if (c >= k) return qsort(nums, right, r, k);
else if (c + b >= k) return key;
else return qsort(nums, l, left, k - b - c);
}
public void swap(int[] nums, int i, int j)
{
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}