米哈游最新一面算法题 求给定的一组无序数组中第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 ≤ 数组的长度。

思路
这题方法有很多
第一种:直接sort(v.begin(),v.end()) 时间复杂度是nlog(n)
第二种:使用堆排序 由于题目需要求第k大,因此我们建立小根堆,最后的堆顶就是第k大,时间复杂度是nlog(k)
第三种方法 我们采用二分的思想并且结合快排。快排的性质是每次都可以将一个数放在最终位置上面,并且左边比此数小,右边比此数大。

快排代码如下:

#include <iostream>
#include<vector>
#include <ctime>
#include<algorithm>
using namespace std;


void quicksort(vector<int> &arr,int left,int right)
{

	int i, j, t, temp;
	if (left > right)
		return;
	temp = arr[left];
	i = left;
	j = right;
	while (i != j)
	{
		while (arr[j] >= temp && i < j)
			j--;
		while (arr[i] <= temp && i < j)
			i++;

		if (i < j)
		{
			t = arr[i];
			arr[i] = arr[j];
			arr[j] = t;
		}
	}

	//交换哨兵和确认所在位置i的数据
	arr[left] = arr[i];
	arr[i] = temp;
	cout << "已确认交换位置 i=" << i << endl;
	quicksort(arr,left,i-1);
	quicksort(arr,  i +1,right);


}



二分法代码:

#include<iostream>
using namespace std;
int binarySearch(int *arr, int low, int high, int target)//递归实现
{
	int middle = (low + high) / 2;
	if (low > high)
		return -1;
	if (arr[middle] == target)
		return middle;
	if (arr[middle] > target)
		return binarySearch(arr, low, middle - 1, target);
	if (arr[middle] < target)
		return binarySearch(arr, middle + 1, high, target);

};

int binarySearch1(int nums[], int n, int target)//循环实现
{
	if (n == 0)
	{
		return -1;
	}
	int hight = n - 1;
	int low = 0;
	int middle;
	while (low <= hight)
	{
		middle = (low + hight) / 2;
		if (nums[middle] > target)
		{
			hight = middle - 1;
		}
		else if (nums[middle] < target)
		{
			low = middle + 1;

		}
		else if (nums[middle] == target)
		{
			return middle;
		}
	}
	return -1;
};

int main()
{
	int a[10] = { 5,6,7,8,9, 10 , 11, 12 ,13, 14 };
	int index = binarySearch(a, 0, 9, 12);
	cout << index << endl;
	int index2 = binarySearch1(a, 10, 12);
	cout << index2 << endl;
	system("pause");
}

此题使用二分法结合快排思想代码如下

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
	int low = 0;
	int high = nums.size() - 1;
	int seg = -1;
	while (seg!=nums.size() - k) {
		seg = partition(nums, low, high);
		if (seg == nums.size() - k)   //第k大 就是 第nums.size()-k小
            {
                cout<<"seg="<<seg;
                break;
            }
			
		else if (seg > nums.size() - k)
			high = seg - 1;
		else
			low = seg + 1;
	}
	return nums[seg];
}

int partition(vector<int>& nums, int low, int high) {
	int i = low;
	int j = high;
	int key = nums[low];
	while (i != j) {
		while (nums[j] >= key && i < j)
			j--;
		while (nums[i] <= key && i < j)
			i++;

		if (i < j)
			swap(nums[i], nums[j]);
	}
	swap(nums[i], nums[low]);   //注意这里swap按引用换值
	return i;
}
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值