【问题标题】:Lowest n Numbers in an Array数组中的最小 n 个数
【发布时间】:2016-12-09 06:04:01
【问题描述】:

如何将一组最小或最大的数字组合到一个数组中?例如,如果我想在大小为 1000 的数组中找到最小的 10 个数字。

我正在使用 C 语言,但我不需要特定语言的答案。我只是想找出一种方法来处理这类任务,因为它最近经常出现。

【问题讨论】:

标签: c arrays algorithm


【解决方案1】:

QuickSelect 算法允许分离预定义的最小和最大数字(无需完全排序)。它使用像快速排序算法这样的分区程序,但是当枢轴找到需要的位置时停止。

【讨论】:

  • 鉴于对int 数组进行排序是O(n)(通过基数排序),而QuickSelectO(n^2) 最坏的情况,我建议进行排序。
  • @EOF 一种方法可能取决于条件 - 如果我们不能允许最坏情况的小概率,我们应该选择另一种方法(例如 - 具有 O(nlogk) 复杂性的二进制堆)。请注意,在一般情况下,Q/S 通常是首选排序。
  • 另一个选项是Introselect,它明确设计用于避免 QuickSelect 的最坏情况(但如果可以承受,将默认使用 QuickSelect)。
【解决方案2】:

方法一:对数组进行排序

您可以对数组进行快速排序并获取前 10 个元素。但这相当低效,因为您只对前 10 个元素感兴趣,并且为此对整个数组进行排序是过大的。

方法2:做一次线性遍历,跟踪10个元素。

int lowerTen = malloc(size_of_array);

//'array' is your array with 1000 elements
for(int i=0; i<size_of_array; i++){
    if(comesUnderLowerTen(array[i], lowerTeb)){
        addTolowerTen(array[i], lowerTen)
    }
}

int comesUnderLowerTen(int num, int *lowerTen){
    //if there are not yet 10 elements in lowerTen, insert.

    //else if 'num' is less than the largest element in lowerTen, insert.
}

void addToLowerTen(int num, int *lowerTen){
    //should make sure that num is inserted at the right place in the array
    //i.e, after inserting 'num' *lowerTen should remain sorted
}

不用说,这不是一个有效的例子。也只有在“lowerTen”数组需要维护少量元素的排序列表时才这样做。如果您需要 1000 个元素数组中的前 500 个元素,这不是首选方法。

方法3:填充原始数组时执行方法2

这仅在您的原始 1000 元素数组被一一填充时才有效 - 在这种情况下,您可以在填充原始数组时维护“lowerTen”数组,而不是对 1000 元素数组进行线性遍历。

方法四:不要使用数组

如果您可以根据原始数组维护像二叉搜索树这样的数据结构,则此类任务会更容易。但同样,在你的数组上构造一个 BST,然后找到前 10 个元素与对数组进行排序然后做同样的事情一样好。仅当您的用例需要搜索一个非常大的数组并且数据需要在内存中时才这样做。

【讨论】:

  • 方法 2 的变体是使用存储在数组中的二进制最大堆来保存最小值(或使用最小堆来存储最大值)。由于二进制最小堆上的操作是 O(1)O(log n),其中 n 是查看的值的数量对于(与 N 是数据集大小相反),这对于 n 远小于 N 的情况特别有用。跨度>
  • 这行有几个问题:int lowerTen = (int*)malloc(size_of_array);。 1) 在 C 中,转换返回值只会使代码混乱。返回的类型是void*,可以分配给任何其他指针,2) malloc() 返回一个指针,但int lowerTen 是整数,而不是指针。
  • 关于这一行:for(int i=0; i&lt;array.length; i++){。在 C 中,数组没有 .length 属性。
  • 谢谢。我的c很生锈。我应该提到这是伪代码。进行了更正
【解决方案3】:

实现一个优先队列。 循环遍历所有数字并将它们添加到该队列中。 如果该队列的长度等于 10,则开始检查当前数字是否低于该队列中的最高数字。 如果是,请删除该最高数字并添加当前数字。

毕竟,您将拥有一个优先级队列,其中包含阵列中 10 个最低的数字。 (所需时间应该是 O(n),其中 n 是数组的长度)。

如果您需要更多提示,请添加评论:)

【讨论】:

    【解决方案4】:

    以下代码

    1. 干净编译
    2. 执行所需的功能
    3. 可能不是最有效的
    4. 处理重复项
    5. 需要修改以处理小于 0 的数字

    现在是代码

    #include <stdlib.h>  // size_t
    
    void selectLowest( int *sourceArray, size_t numItemsInSource, int *lowestDest, size_t numItemsInDest )
    {
        size_t maxIndex = 0;
        int    maxValue = 0;
    
        // initially populate lowestDest array
        for( size_t i=0; i<numItemsInDest; i++ )
        {
            lowestDest[i] = sourceArray[i];
            if( maxValue < sourceArray[i] )
            {
                maxValue = sourceArray[i];
                maxIndex = i;
            }
        }
    
        // search rest of sourceArray and 
        // if lower than max in lowestDest, 
        // then 
        //    replace
        //    find new max value 
        for( size_t i=numItemsInDest; i<numItemsInSource; i++ )
        {
            if( maxValue > sourceArray[i] )
            {
                lowestDest[maxIndex] = sourceArray[i];
    
                maxIndex = 0;
                maxValue = 0;
                for( size_t j=0; j<numItemsInDest; j++ )
                {
                    if( maxValue < lowestDest[j] )
                    {
                        maxValue = lowestDest[j];
                        maxIndex = j;
                    }
                }
            }
        }
    } // end function: selectLowest
    

    【讨论】:

      猜你喜欢
      • 2023-01-25
      • 2020-08-09
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 2016-03-20
      • 1970-01-01
      • 2011-02-16
      相关资源
      最近更新 更多