用二分法和堆寻找第K大元素

Problem description

Find the kth largest element in an unsorted array A . Note that it is the kth largest element in the sorted order, not the kth distinct element. The range of length of A is N(1≤N≤5,000,000) and the element (integer) in A is no bigger than 10,000,00000.

Input

Line 1: the length of the unsorted array A and the index k. Line 2: the all elements in array A and split by spaces

Output

Line 1: A single integer that is the kth largest element in an unsorted array A.

Sample Input 1

8 2
1 3 5 7 4 2 6 8

Sample Output 1

7

Sample Input 2

8 2
1 1 2 2 3 3 4 4

Sample Output 2

4

 

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<queue>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<vector>
using namespace std;
/*
	p:数组
	k:第k大
	l:指向数组第一个元素的下标 
	r:指向数组最后一个元素的下标
	初始状态l=0,r=数组长度-1
	时间复杂度为O(n)
	关键在于选取pivot能否每次都将数组均匀的划分成左右两半
*/
void binarySearch(int* p, int k, int l, int r) {
	int left = l;
	int right = r;
	int pivot = p[l];
	while (left < right)
	{
		while (p[right] <= pivot && left < right) right--;
		p[left] = p[right];
		while (p[left] >= pivot && left < right) left++;
		p[right] = p[left];
	}
	p[left] = pivot;
	if (left == k - 1) cout << pivot;
	else if (left > k - 1) binarySearch(p, k, l, left-1); //要找的第K大元素在pivot划分后的数组的左边
	else binarySearch(p, k - left, left+1, r);//要找的第K大元素在pivot划分后的数组的右边
}
/*
	p:数组
	k:第k大
	n:数组长度
	时间复杂度为O(nlogk)
	适用于k较小或较大,k如果较大就用大根堆,求n-k+1小的元素
*/
void priorityQueue(int* p, int n, int k)
{
	priority_queue<int, vector<int>, greater<> > q;
	for (int i = 0; i < k; i++)
	{
		q.push(p[i]);
	}
	for (int i = k; i < n; i++)
	{
		if (q.top() < p[i])
		{
			q.pop();
			q.push(p[i]);
		}
	}
	cout << q.top();
}
int main() {
	int n, k;
	scanf("%d %d", &n, &k);
	int* p = new int[n];
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &p[i]);
	}
	//binarySearch(p, k, 0, n - 1);
	priorityQueue(p, n, k);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值