【问题标题】:How to find number of elements greater/smaller than an element in an array?如何查找大于/小于数组中元素的元素数?
【发布时间】:2015-08-22 19:53:44
【问题描述】:

我想找到最快的方法来查找小于/大于数组中每个元素的元素数量。

例如:数组是[5, 6, 8, 2, 4]。考虑到第一个元素,没有小于它的元素是 2。

我能做的最好的事情就是将每个元素与数组的其余元素进行比较,但对于条目数约为 10^5 的大型数组来说,这需要很长时间。

我的代码:

for(i=0;i<n;i++)
{
    count=0;
    for(j=0;j<n;j++)
    {
        if( i!=j && (ar[i]>ar[j]) )
        {
            count++;
        }
    }
    printf("%lld ",count);
}

编辑:我想显示小于每个数组元素的元素数。对于上面的例子,我希望答案是:2 3 4 0 1 数组可以包含重复值。

【问题讨论】:

  • 您的问题是,如果您想要确切的正确答案,您要么必须遍历整个库存(因为您不知道下一个元素将是什么),要么对其进行排序,或者使用一些其他启发式方法,并粗略估计下一个元素可能是什么。
  • 检查这个。它会帮助你。stackoverflow.com/questions/30672430/…

标签: c arrays algorithm performance search


【解决方案1】:

以下代码 sn-p 将帮助您进行查询。
它是使用 二分搜索 实现的,因此可以做到 log(n) 时间复杂度,
其中 n 是数组中的元素数。

请注意,您需要先对数组进行排序。
因此总体时间复杂度为n*log(n)。

#include<bits/stdc++.h>
using namespace std;

int binarySearchLargerElenents(int arr[], int val){
    int l = 0;
    int size = sizeof(arr)/sizeof(arr[0]);
    int r = size-1;
    int resultantIndex = size;
    while(l<=r){
        int mid = l + (r-l) / 2;
        if(arr[mid] <= val){
            l = mid +1;
        }
        else{
            r = mid -1;
            resultantIndex = mid;
        }
    }
    return (size-resultantIndex);
}

int binarySearchSmallerElements(int arr[], int val){
    int l = 0;
    int size = sizeof(arr)/sizeof(arr[0]);
    int r = size-1;
    int resultantIndex = size;
    // strictly less than val.
    // while(l<=r){
    //   int mid = l + (r - l) / 2;
    //   if(arr[mid] < val){
    //     l = mid + 1;
    //
    //   }
    //   else{
    //     r = mid - 1;
    //     resultantIndex = mid;
    //   }
    // }

    // less that or equal to val
    while(l<=r){
        int mid = l + (r-l) / 2;
        if(arr[mid] <= val){
            l = mid +1;
        }
        else{
            r = mid-1;
            resultantIndex = mid;
        }
    }
    return resultantIndex;
}
int main(){
    int arr[] = {1, 2, 3, 4, 5, 5, 7};
    int x;
    cout<<"Input x: ";
    cin>>x;
    int countOfSmallerElements = binarySearchSmallerElements(arr, x);
    int countOfLargerElements = binarySearchLargerElenents(arr, x);

    cout<<" smaller than "<<x <<" : "<< countOfSmallerElements<<endl;
    cout<<" larger than "<<x <<" : "<< countOfLargerElements<<endl;
}

【讨论】:

    【解决方案2】:

    正如其他人所说,您可以通过对数组进行排序,然后为每个元素 x 找到低于/高于 x 的第一个数字的索引,在 O(nlogn) 中解决它。

    我想证明问题的下限:
    不能比Omega(nlogn)在代数树模型下做得更好(这基本上意味着没有散列)。

    证明:我们将通过减少Element Distinctness Problem 来证明它。
    假设我们有一个算法A 可以解决O(f(n)) 中的这个问题
    给定一个数组arr,在该数组上调用A。结果是一个新数组res,其中res[i] 是低于arr[i] 的元素数。
    请注意,对于任何两个索引i,jres[i] == res[j] iff arr[i] == arr[j]
    这个,arr 中存在重复,如果 res 中存在重复。
    但是,res 中的所有元素都在[0,n-1] 范围内。这意味着我们有一个元素区别问题,其中所有元素都以n 为界。
    这个变种可以在O(n)使用桶排序的修改来解决。

    所以,我们基本上展示了解决O(n + f(n))中的问题(Element Distinctness)的算法,但是由于该模型下的元素区别是Omega(nlogn)问题,这意味着f(n)本身必须在Omega(nlogn)

    QED

    【讨论】:

    • @IvayloStrandjev 在代数树模型下不能比 Omega(nlogn) 做得更好。其中“It”是问题的要求:获取res[i] = number of elements lower than arr[i]的数组
    • @IvayloStrandjev 不,天真的方法是二次方。问题要求为 ALL x 获取低于 x 的元素数。
    • @IvayloStrandjev 从来没有,但是嗯......(问题的第一行和算法都澄清它适用于所有元素,并且从未编辑过)
    • @IvayloStrandjev 问题陈述中的更改在编辑部分。其他一切都没有改变:)
    【解决方案3】:

    如果您计划执行单个类似查询,则无法改进您已经提出的线性方法。但是,如果您计划执行许多类似的查询,您可以对数组进行排序,然后对每个查询执行二进制搜索。这将导致每个查询的O(n*log(n)) 预计算复杂性和O(log(n)) 复杂性。请注意,仅当您计划执行的查询超过 O(log(n)) 时,此方法才会有所改进。

    【讨论】:

      【解决方案4】:

      最简单的技巧是先对数组进行排序,然后计算数组中元素的数量。因此,例如,如果您有 10 个元素,那么您的第一个元素小于 9,同样第二个元素小于 8,依此类推。

      一个例外是你有两个相同的项目,你只需要比较两个项目,第一个和下一个。我认为这是最可行的解决方案。

      【讨论】:

        【解决方案5】:

        对数组进行排序。 现在,对于每个查询,您可以将 O(log n) 时间减少到 O(1) 时间。 创建一个哈希映射。循环遍历排序数组的每个元素,并用元素作为键和排序位置作为其值填充 HashMap。 HashMap 提供 O(1) 查找,因此它比对每个查询的二分查找更省时。

        【讨论】:

          【解决方案6】:

          最好的方法是使用 Fenwick Trees/Binary Indexed Trees....那些数据结构是专门为这类问题制作的通过输入...

          【讨论】:

            【解决方案7】:

            一个简单的方法是:

            1. 首先对数组进行排序,可能使用qsort()
            2. 对排序后的数组执行binary search
            3. 根据数组的大小所需元素计算剩余元素。

            【讨论】:

            • 先复制数组,否则无法给出想要的答案。并考虑到数组元素可以通过修改二进制搜索来相等,以便它将给出等于 x 的 last 元素的索引。否则,如果所有元素只有一个或两个不同的值,您将返回二次时间。
            • @gnasher729 感谢您提供详细信息。没错,确实。 :-)
            • 应该如何修改二分搜索以考虑到数组中的重复值。
            • @SwapnilPandey 请原谅我,但是在排序时不是很小心吗?我的意思是重复值的处理将根据排序算法进行定义。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-27
            • 2014-11-08
            • 1970-01-01
            • 2020-02-04
            • 2015-03-11
            • 2021-07-19
            相关资源
            最近更新 更多