题目意思就是在一个很大的无序数组中,找到第N位大的数
思路一:直接暴力!
利用Sort函数直接进行快排,然后把对应位数代入下标直接输出,复杂度在O(nlogn)
思路二:动态规划
定义一个大小为n的数组A[n],虽然题目上是一个很大的无序数组,但是我们可以简化来看,如果这个无序数组大小恰好为n,那么就是输出这个无序数组的最小值(第n位大,就是最小的那个值)。
现在用A[n]来存无序数组这n个数,在此基础上假设无序数组大小为n+1,现在多了一个数,那么多出来的这个数想要成为第N位大的数,那么它首先要比现在A[n]里的最小数大,否则无论如何它都进不了前N位。
所以进行判断如果第n+1个数大于A[n]里最小值,那么就替换掉这个最小值(n+1这位数替换进去后不一定是A[n]里最小的)。然后就是依次类推,n+2..n+3..,最后A[n]里的最小值就是要输出的值
思路三:分治算法
即把该无序数组分成很多个小数组,每个小数组里面找到该小数组对应的第N位大的数,然后去找所有小数组对应的第N位大的数中的第N位大的数,不过暂时没想到很好的切割方法,所以采用了动态规划。
源码:
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
double Test[10000]; //定义测试数组
//重载swap
void swap(double* a, double* b)
{
int temp = 0;
temp = *a;
*a = *b;
*b = temp;
}
//堆排序维护
void Fixheap(double a[],int n,int i)
{
int largest = i;
int lson = i * 2 + 1;
int rson = i * 2 + 2;
if (lson<n && a[largest]>a[lson])
{
largest = lson;
}
if (rson<n && a[largest]>a[rson])
{
largest = rson;
}
if (largest != i)
{
swap(&a[largest], &a[i]);
Fixheap(a, n, largest);
}
}
//建堆
void heap_sort(double a[], int n)
{
int i;
for (i = n / 2 - 1;i >= 0;i--)
{
Fixheap(a, n, i);
}
}
int main()
{
for (int i = 0;i < 10000;i++) //随机生成数据
{
Test[i] = rand() % 9999*1.0 + 1;
}
int n;
cout << "请输入要找的第N位最大数";
cin >> n;
double* b = new double[n];
int time1 = 0;
for (int i = 0;i < 1000;i++)
{
if (time1 < n)
{
b[i] = Test[i];
if (time1 == n - 1)
{
heap_sort(b, n);
}
time1++;
}
else
{
//每次重新堆维护
Fixheap(b, n,n/2-1);
if (Test[i] > b[0])
{
b[0] = Test[i];
}
}
}
cout<< "第" << n << "位最大值为:";
cout << b[0];
/* 方法二
vector<double> out; //定义一个vector动态数组
int time = 0; //用于计数,即先把前n个数存到out数组中
for (int i = 0;i < 1000;i++)
{
if (time < n)
{
out.push_back(Test[i]);
time++;
}
else
{
//找到当前数组中的最小值,如果接下来Test数组中的数大于这个最小值那么便把它替换掉
int minnum = min_element(out.begin(), out.end()) - out.begin();
if (Test[i] > out[minnum])
{
out[minnum] = Test[i];
}
}
}
int minnum = min_element(out.begin(), out.end()) - out.begin();
cout << "第" << n << "位最大值为:";
cout << out[minnum] << " ";
*/
}