编程之美2.5-寻找最大的k个数

本文介绍了一种高效算法用于从一组数值中找出最大的K个数。通过使用小根堆结构,该算法能够快速筛选并返回所需数值。此外,还探讨了其他几种解法,包括排序、快速排序结合递归等方法。

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

解法零:

首先想到堆排序

假设从十个数中寻找三个最大的数

将前三个数建立小根堆(用数组a记录),遍历剩下的(10 - 3)个数字,对其做如下循环:

1.取出下一个数字(假设是i),将其与小根堆中的根比较,若其小于根节点,则不作任何处理,直接处理剩余数字中的下一个

2.若大于根节点,则删除小根堆中的根节点,将i插入a中

3.处理剩余数字中的下一个

遍历完成后,输出小根堆a,即为所求的最大的k个数

code:

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

using namespace std;

void Swap(int &a,int &b)
{
	int temp = a;
	a = b;
	b = temp;
}
void Print(int *a,int n)
{
	for(int i = 0 ; i < n ; ++i)
		cout<<a[i]<<" ";
	cout<<endl;
}
void MinHeapFixDown(int *a,int i,int n)
{
	int j = 2 * i +1;
	int temp = a[i];
	while(j < n)
	{
		if(j+1<n&&a[j]>a[j+1])
			j++;
		if(temp < a[j])
			break;

		a[i] = a[j];
		i = j;
		j = i*2+1;
	}
	a[i] = temp;
}
bool MinHeapDelNum(int *a,int n,int i)
{
	if(i < a[0])
		return false;
	Swap(a[0],a[n]);
	MinHeapFixDown(a,0,n);
	return true;
}
void MinHeapFixUp(int *a,int i)
{
	for(int j = (i - 1) / 2 ; (j >= 0)&&(i != 0)&&(a[j] > a[i]) ; i = j , j = (i - 1) / 2)
		Swap(a[i],a[j]);
}
void MinHeapAddNum(int *a,int n,int i)
{
	a[n] = i;
	MinHeapFixUp(a,n);
}
void heap(int *a,int aNum,int *p,int pNum)
{
	for(int i = 0 ; i < pNum ; ++i)
	{
		if(i < aNum)
			MinHeapAddNum(a,i,p[i]);
		else
		{
			if(MinHeapDelNum(a,aNum - 1,p[i]) == true)
				MinHeapAddNum(a,aNum - 1,p[i]);			
		}
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	int a[3] = {0};
	int p[10] = {4,6,2,5,7,11,54,35,66,1};
	heap(a,3,p,10);
	Print(a,3);
	return 0;
}
书上的解法:

解法一:排序,取前K个数

解法二:

快排&递归,每次将待排数据分为左右两组Sa和Sb

1.Sa中元素个数小于K,数组S中最大的K个数:Sa的全部和Sb中最大的K-|Sa|

2.Sa中元素个数大于等于K,返回Sa中最大的K个数

解法三:???

解法四:即解法零

解法五:当所有N个数都是正整数且取值范围不大时,可考虑直接使用数组记录每个整数出现次数得出结论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值