[英]Maximum X values at array
我正在尝试编写一个函数,该函数需要数组,数组的大小和X个最大等级的数量。
例如:
array = { 90,45,77,43,67,88 }, maxGrades = 3
结果应为:
retArray = {90,77,88} or {90,88,77}
我尝试过的是:
int * GetMaxGrades(int * grades, int size, int maxGrades)
{
int *retArray;
if (maxGrades > size)
return grades;
retArray = (int*)calloc(sizeof(int) * maxGrades);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < maxGrades; j++)
if (grades[i] > retArray[j])
{
retArray[j] = grades[i];
break;
}
}
return retArray;
}
但我复活了{90,88,67}
编辑如果我这样更改内部循环:
if (grades[i] > retArray[j])
{
if (j + 1 < maxGrades)
retArray[j + 1] = retArray[j];
retArray[j] = grades[i];
break;
}
它解决了部分问题,但这是最好的方法吗?
虽然可以使用选择算法在线性时间内完成,但通常使用最小堆来存储前k个元素,每次迭代-您检查堆中最小的元素是否大于当前的最大元素正在迭代,如果是,则将其替换。
这是O(nlogk)
时间,只有O(k)
额外的内存,并且只需要对数据进行一次遍历(因此,如果您的元素进入流中,它将完美地工作)。
以下代码是C ++ 11(具有优雅的for-each循环),但是使用相同的数据结构很容易将其转换为旧的c ++代码。
#include <iostream>
#include <vector>
#include <queue>
int main(void) {
int array[] = { 90,45,77,43,67,88 };
int maxGrades = 3;
std::priority_queue<int, std::vector<int>, std::greater<int>> q;
for (int x : array) {
// populate first maxGrades elements
if (q.size() < maxGrades) {
q.push(x);
// replace if new element is higher than smallest in heap.
} else if (q.top() < x) {
q.pop();
q.push(x);
}
}
// print elements
std::cout << "elements: ";
while (!q.empty()) {
std::cout << q.top() << " ";
q.pop();
}
return 0;
}
可以使用QuickSort发明者的QuickSelect算法以O(N)个平均复杂度从大小为N的数组中选择X个最大值: https ://en.wikipedia.org/wiki/Quickselect
在上一次循环迭代的开始,您的retArray如下所示: {90,77,67}
。 如果您通过i=5
遍历内部循环,则会发现77位于67之前,因此77被替换了。 您可能应该对数组进行排序并采用最高的maxGrades值,但如果要这样做,请按照以下步骤操作:
for(...)
if(grades[i] > retArray[j])
if(retArray[j] < retArray[minVal])
minVal = j;
if(minVal > 0)
retArray[minVal] = grades[i];
minVal = -1;
如果您的grades
数组可能包含重复项,则解决方案将变得更加困难。 并且不要忘记,如果您将指针返回给grades
数组,则调用者可能不知道是否应该释放返回的指针。
#include <stdio.h>
#include <stdlib.h>
int* GetMaxGrades(int* grades, int size, int maxGrades) {
if (maxGrades <= 0 || size <= 0)
return NULL;
// first, function must allocate memory every time,
// otherwise you can't understand when to free memory or when do not it.
int *retArray = (int*)malloc(sizeof(int) * maxGrades);
if (maxGrades >= size) {
for (int i = 0; i < size; ++i)
retArray[i] = grades[i];
for (int i = size; i < maxGrades; ++i)
retArray[i] = 0;
}
else {
// need to save positions of found max grades,
// because if there's duplicates among grades,
// you will pick up only different onces.
int *positions = (int*)malloc(sizeof(int) * maxGrades);
for (int i = 0; i < maxGrades; ++i) {
int position = 0;
int maxgrade = INT_MIN;
for (int j = 0; j < size; ++j) {
// pick max grade
if (grades[j] > maxgrade) {
// do not permit duplicates among positions
bool newmax = true;
for (int k = 0; k < i; ++k) {
if (positions[k] == j) {
newmax = false;
break;
}
}
// assign new max value & position
if (newmax) {
position = j;
maxgrade = grades[j];
}
}
}
positions[i] = position;
retArray[i] = maxgrade;
}
free(positions);
}
return retArray;
}
int main(int argc, char* argv[]) {
int a[] = { 90,45,77,43,67,88 };
const int max_grades = 3;
int *p = GetMaxGrades(a, sizeof(a) / sizeof(a[0]), 3);
for (int i = 0; i < max_grades; ++i) {
printf("%d ", p[i]);
}
printf("\n");
free(p);
return 0;
}
如果允许您使用qsort
,它将变得更加容易:
#include <stdio.h>
#include <stdlib.h>
int greater_comp(const void * a, const void * b) {
return *(int*)b - *(int*)a;
}
int* GetMaxGrades(int* grades, int size, int maxGrades) {
if (maxGrades <= 0 || size <= 0)
return NULL;
int alloc_size = (maxGrades < size) ? size : maxGrades;
// copy grades array (allocate more memory)
int *retArray = (int*)malloc(sizeof(int) * alloc_size);
for (int i = 0; i < size; ++i)
retArray[i] = grades[i];
for (int i = size; i < alloc_size; ++i)
retArray[i] = 0;
// sort: descending order
qsort(retArray, size, sizeof(int), greater_comp);
return retArray;
}
int main(int argc, char* argv[]) {
int a[] = { 90,45,77,43,67,88 };
const int max_grades = 3;
int *p = GetMaxGrades(a, sizeof(a) / sizeof(a[0]), 3);
for (int i = 0; i < max_grades; ++i) {
printf("%d ", p[i]);
}
printf("\n");
free(p);
return 0;
}
而且,如果您要使用算法库,它将变得更加容易:
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
vector<int> GetMaxGrades(vector<int> grades, int maxGrades) {
// descending order
sort(grades.begin(), grades.end(), greater<int>());
grades.resize(maxGrades);
return grades;
}
int main(int argc, char* argv[]) {
vector<int> a = { 90,45,77,43,67,88 };
vector<int> p = GetMaxGrades(a, 3);
for (auto& i : p)
cout << i << ' ';
cout << endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.