繁体   English   中英

数组的最大X值

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM