215.数组中的第K个最大元素(leetcode)

本文介绍了一种在未排序数组中查找第k个最大元素的方法,通过快速排序和改进的枢轴选择策略,实现了高效的搜索算法。文章详细解释了两种快速排序的实现方式,并提出了一种更优的解决方案,仅需一次遍历即可找到目标元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在未排序的数组中找到第 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 ≤ 数组的长度。

 

解决方案:

方法一:

首先使用快速排序把数组从大到小进行排序,然后从排好序的数组中找出第k大的值,代码如下:

class Solution {
public:
vector<int> QuickSort(vector<int> s)
{
	int len = s.size();
	if (len <= 1)
		return s;
	int mid = s[len / 2];
	vector<int> left;
	vector<int> right;
	vector<int> equal;
	for (int i = 0; i < len; i++)
	{
		if (s[i] > mid)
			left.push_back(s[i]);
		else if (s[i] < mid)
			right.push_back(s[i]);
		else
			equal.push_back(s[i]);
	}
	vector<int> left_final = QuickSort(left);
	vector<int> right_final = QuickSort(right);
	vector<int> res;
	res.insert(res.end(), left_final.begin(), left_final.end());
	res.insert(res.end(), equal.begin(), equal.end());
	res.insert(res.end(), right_final.begin(), right_final.end());
	return res;
}
    int findKthLargest(vector<int>& nums, int k) {
        vector<int> res = QuickSort(nums);
        return res[k-1];
    }
};

由于本人是小白,快速排序写的十分的繁琐,因此接下来,我会展示一种比较简洁的快速排序方式:左右指针法

1. 首先选取一个值作为pivot,一般取数组记录中的第一个或者最后一个,这里面选取第一个元素。
2. 设置两个变量,l = left + 1, r = right。其中left是需要处理的数组的最左索引,而right是需要处理的数组的最右索引。
3.从l一直往右走,直到找到一个比pivot小的元素;从r一直往左走,知道找到一个比pivot大的元素,然后交换这两个数的位置。
4.重复第三步,一直往后找,知道 l 和 r 相遇,这是将pivot放置在 r 所在的位置。

其中代码如下:

class Solution {
public:
int PartSort(vector<int> &s, int left, int right)
{
	int pivot = s[left];
	int l = left + 1, r = right;
	while (l <= r)
	{
		if (s[l]<pivot && s[r]>pivot)
			swap(s[l++], s[r--]);
		if (s[l] >= pivot)
			l++;
		if (s[r] <= pivot)
			r--;
	}
	swap(s[left], s[r]);
	return r;
}

void QuickSort(vector<int> &s, int left, int right)
{
	if (left > right)
		return;
	int index = PartSort(s, left, right);
	QuickSort(s, left, index - 1);
	QuickSort(s, index + 1, right);
}
    
    int findKthLargest(vector<int>& nums, int k) {
        QuickSort(nums, 0, nums.size()-1);
        return nums[k-1];
    }
};

方法二:

对于这道题来说,仅仅需要求出第k大的数值,因此没必要把整个数组先排了序再求。因此使用快速排序的核心思想是,每次都要找到一个中枢点pivot,然后遍历其他所有的数字,比如说这道题,将所有大于pivot的值放在中枢点的左边,小于pivot的值放在中枢点的右边,这样子执行一遍排序后,整个数组的第几大的数字就确定了,虽然左右两边不一定是有序的,但是并不影响实验的要求。因此,如果我们求出的中枢点的位置正好是k-1,则直接返回该位置上的数字;如果大于k-1,说明要求的数字在左半部分,更新有边界,再求出新的中枢点进行比较;反之则更新右半部分。

class Solution {
public:
int PartSort(vector<int> &s, int left, int right)
{
	int pivot = s[left];
	int l = left + 1, r = right;
	while (l <= r)
	{
		if (s[l]<pivot && s[r]>pivot)
			swap(s[l++], s[r--]);
		if (s[l] >= pivot)
			l++;
		if (s[r] <= pivot)
			r--;
	}
	swap(s[left], s[r]);
	return r;
}

void QuickSort(vector<int> &s, int left, int right)
{
	if (left > right)
		return;
	int index = PartSort(s, left, right);
	QuickSort(s, left, index - 1);
	QuickSort(s, index + 1, right);
}
    
    int findKthLargest(vector<int>& nums, int k) {
        int left = 0, right = nums.size() - 1;
	    while (true)
	    {
		    int index = PartSort(nums, left, right);
		    if (index == k - 1)
			    return nums[index];
		    else if (index > k - 1)
			    right = index - 1;
		    else
			    left = index + 1;
	    }
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值