C++实现topK——前k大的数、第k大的数,基于堆排,快排

基于堆排序

// topK.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;


void adjustHeap(vector<int>& arr, int begin,int end) //下沉,维护小根堆
{
	int dad = begin, son = 2 * dad + 1;
	while (son <= end){
		if (son + 1 <= end&&arr[son] > arr[son + 1]) son++;
		if (arr[dad] < arr[son]) return;
		else{
			swap(arr[dad], arr[son]);
			dad = son;
			son = 2 * dad + 1;
		}
	}
	
}

void creatHeap(vector<int>& arr, int len)
{
	for (int i = len / 2 - 1; i >= 0; i--){
		adjustHeap(arr, i, len - 1);
	}
}
int main()
{
	int k = 5;
	vector<int> nums = { 3,1,6,8,2,0,4,66,12 };
	vector<int> heap; //始终要维护的堆
	for (int i = 0; i < k; ++i) //加入k个数建堆
	{
		heap.push_back(nums[i]);
	}
	creatHeap(heap, k);
	for (int i = k; i < nums.size(); i++){ //新来的数字与堆顶比较,如果大于堆顶元素就替换掉它,再重新下沉维护小根堆
		if (nums[i]>heap[0]){
			heap[0] = nums[i];
			adjustHeap(heap, 0, k - 1);
		}
	}

	//输出前k大的所有k个数
	for (int i = 0; i < heap.size(); i++)
	{
		cout << heap[i] << " ";
	}

	//输出第k大的数
	cout << heap[0] << endl;
	return 0;
}


时间复杂度O(nlogK),n是所有数字个数,K是堆大小


基于快排

// topK.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>

using namespace std;

int Partition(vector<int> &nums, int left, int right){ //分区,返回基准数字的索引
	int key = nums[left];
	int i = left, j = right;
	while (i < j){
		while (i < j&&nums[j] <= key) j--;
		nums[i] = nums[j];
		while (i < j&&nums[i] >= key) i++;
		nums[j] = nums[i];
	}
	nums[i] = key;
	return i;
}



int qSearch(vector<int>& arr, int left, int right, int k){
	//只排序固定区间的前k个数
	int pos = -1, len = 0; //len指的是目前取到了前多少个数
	int i = left, j = right;
	if (i < j){
		pos = Partition(arr, i, j);
		len = pos - i + 1; //是包括本身的长度
		if (len < k){
			pos = qSearch(arr, pos + 1, right, k - len);
		}
		else if (len>k){
			pos = qSearch(arr, left, pos - 1, k);
		}
	}
	return pos;
}


int main(){
	vector<int> nums{ 1, 45, 2, 3, 46, 0, 44, 6,12,456677,23,12,22,-10,444444,132422 };

	int k = 3;
	qSearch(nums, 0, nums.size() - 1, k);
	
	for (int i = 0; i < k; i++){ 
		cout << nums[i] << endl;
	}
}

时间复杂度O(n)

面试常考的,一定要会啊!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值