设计一组N个数,确定其中第k个最大值

本文探讨了多种在无序数组中查找第k大数值的方法,包括排序、选择排序、快速排序思想的应用等,并提供了解法3的具体实现代码。

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

今天看算法分析是,看到一个这样的问题,就是在一堆数据中查找到第k个大的值。

      名称是:设计一组N个数,确定其中第k个最大值,这是一个选择问题,当然,解决这个问题的方法很多,本人在网上搜索了一番,查找到以下的方式,决定很好,推荐给大家。

      所谓“第(前)k大数问题”指的是在长度为n(n>=k)的乱序数组中S找出从大到小顺序的第(前)k个数的问题。

      解法1: 我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*logn + k)。
      解法2: 利用选择排序或交互排序,K次选择后即可得到第k大的数。总的时间复杂度为O(n*k)
      解法3: 利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
           1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
           2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)
      解法4: 二分[Smin,Smax]查找结果X,统计X在数组中出现,且整个数组中比X大的数目为k-1的数即为第k大数。时间复杂度平均情况为O(n*logn)
      解法5:用O(4*n)的方法对原数组建最大堆,然后pop出k次即可。时间复杂度为O(4*n + k*logn)
      解法6:维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中。时间复杂度O(n * logk)
      解法7:利用hash保存数组中元素Si出现的次数,利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)

这里实现的是解法3
#include<iostream>
#include<stdio.h>
using namespace std;

int Partition (int *L, int low, int high)
{
int temp = L[low];
int pt   = L[low]; //哨兵
while (low != high)
{
while (low < high && L[high] >= pt)
high--;
L[low] = L[high];

while (low < high && L[low] <= pt)
low++;
L[high] = L[low];
}

L[low] = temp;
return low;
}

void QSort (int *L, int low, int high)  //快速排序
{
int pl;
if (low < high)
{
pl = Partition (L,low,high);
QSort (L, low,  pl-1);
QSort (L, pl+1, high);
}
}
void findk(int k,int *L,int low,int high)
{
int temp;
temp=Partition(L,low,high);
if(temp==k-1)
{
cout<<"第"<<temp+1<<"大的数是:"<<L[temp]<<endl;
}
else if(temp>k-1)
findk(k,L,low,temp-1);
else
findk(k,L,temp+1,high);

}

int main()
{
int a[10]={15,25,9,48,36,100,58,99,126,5},i,j,k;
cout<<"排序前:"<<endl;
for(i=0;i<10;i++){
cout<<a[i]<<" ";
}
cout<<endl;
cout<<"请输入你要查找第k大的数:"<<endl;
cin>>k;
findk(k,a,0,9);
QSort(a,0,9);

cout<<"排序后:"<<endl;
for(i=0;i<10;i++){
cout<<a[i]<<" ";
}
cout<<endl;
system("Pause");
return 0;

}
确定第K个最大值,你可以使用快速选择算法。该算法基于快速排序的思想,但不需要对整个数组进行完全排序,而只需要在部分数组中进行递归操作。 以下是一种基于快速选择算法的实现方法: ```c #include <stdio.h> int partition(int arr[], int low, int high) { int pivot = arr[high]; // 选取最后一个元素作为基准值 int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] <= pivot) { i++; // 交换元素 int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } // 将基准值放入正确的位置 int temp = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp; return i + 1; } int quickSelect(int arr[], int low, int high, int k) { if (low <= high) { int pivotIndex = partition(arr, low, high); // 如果基准值的索引等于K-1,说明找到了第K个最大值 if (pivotIndex == k - 1) { return arr[pivotIndex]; } // 如果基准值的索引于K-1,说明第K个最大值在基准值的左侧 else if (pivotIndex > k - 1) { return quickSelect(arr, low, pivotIndex - 1, k); } // 如果基准值的索引小于K-1,说明第K个最大值在基准值的右侧 else { return quickSelect(arr, pivotIndex + 1, high, k); } } return -1; // 错误情况 } int findKthLargest(int arr[], int n, int k) { return quickSelect(arr, 0, n - 1, k); } int main() { int arr[] = {10, 5, 8, 12, 3}; int n = sizeof(arr) / sizeof(arr[0]); int k = 3; int kthLargest = findKthLargest(arr, n, k); printf("The %dth largest number is: %d\n", k, kthLargest); return 0; } ``` 在该示例代码中,数组arr为输入的N个数,变量n表示数组小,变量k表示要找出的第K个最大值。输出结果为第K个最大值。你可以根据实际需求进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值