【问题标题】:algorithm: find count of numbers within a given range算法:查找给定范围内的数字计数
【发布时间】:2017-05-13 21:10:03
【问题描述】:

给定一个可能存在重复的未排序数字数组,对数组进行预处理,以便找到给定范围内的数字计数,时间为 O(1)。

例如,7,2,3,2,4,1,4,6>= 2<= 5 的数字计数为 5(2,2,3,4,4).

【问题讨论】:

  • “预处理”部分是 O(1) 吗?我不明白这怎么可能。我猜你的意思是对数组进行预处理,以便结果可以计算 O(1) 中给定条件的数量?
  • 听起来像家庭作业?如果是,请标记它。
  • 允许的最小/最大范围是多少?

标签: c++ algorithm


【解决方案1】:

对数组进行排序。对于排序数组中的每个元素,将该元素插入到哈希表中,元素的值作为键,其在数组中的位置作为关联值。任何被跳过的值,您也需要插入。

要查找范围内的项目数,请在哈希表中查找范围两端的值的位置,然后从上减去下以找到范围的大小。

【讨论】:

  • 我只会在输入数组从不稀疏的情况下这样做,否则您可能会构建一个非常大的哈希映射。或者将每个元素的单独计数存储在哈希映射中并检查范围内的每个项目。不过不会是 O(1)。
  • 该解决方案如何处理原始数组中的重复数字?对于 OP 的示例,您如何区分前 4 个和第二个?
  • @pmr:是的,如果您的输入非常稀疏,这将是非常浪费的。 @DShook:你有几个选择。两个明显的方法是跟踪第一个和最后一个位置,以及跟踪第一个位置和相等元素的数量。
  • 您可以通过分桶来节省一些空间。因此,如果输入范围是 [l,u],您会在 l 和 u 附近寻找最接近的 10 的倍数,并将其用于哈希查找。然后对不超过 20 个额外/遗漏的项目进行另一次哈希查找。
  • 没有理由使用哈希表,因为您要为 [MIN, MAX] 范围内的每个键插入一个键值对。只需使用一个数组。
【解决方案2】:

这听起来有点像一些面试官喜欢问的聪明的面试问题之一,通常伴随着提示,以了解你的想法。

无论如何...实现这一点的一种可能方法是制作一个等于或小于列表索引的数字计数列表。

例如,从上面的列表中,生成列表:0, 1, 3, 4, 6, 6, 7, 8。然后您可以通过从 list[ 中减去 list[1] 来计算 2 到 5 之间的数字5]。

【讨论】:

  • 即便如此,只有当数字本身来自有限范围(例如,如果它们保证适合常规 int)时,它才是 O(1)。
  • 为了迂腐,如果您的列表类型不适合常规 int,它不会停止为 O(1)...它完全停止工作(因为所需的内存超过了可寻址的许多/大多数系统上的空间)。但是,该系统可以处理大于 int 的任何数量的值计数。因为没有理由生成的计数数组不能使用比 uint 更复杂的东西作为计数器。
【解决方案3】:

由于我们需要在 O(1) 中访问,因此所需的数据结构将是内存密集型的。
使用哈希表,在最坏的情况下访问需要 O(n)

我的解决方案:
构建二维矩阵。
数组 = {2,3,2,4,1,4,6} 数字范围 = 0 到 6 所以 n = 7
所以我们必须创建 nxn 矩阵。
array[i][i] 表示元素的总数 = i
所以 array[4][4] = 2(因为 4 在数组中出现了 2 次)
数组[5][5] = 0
array[5][2] = >= 2 和

//preprocessing stage 1: Would populate a[i][i] with total count of element = i
a[n][n]={0};
for(i=0;i<=n;i++){
  a[i][i]++;
}

//stage 2
for(i=1;i<=n;i++)
  for(j=0;j<i;j++)
     a[i][j] = a[i-1][j] + a[i][i];
//we are just adding count of element=i to each value in i-1th row and we get ith row.

现在 (5,2) 将查询 a[5][2] 并在 O(1) 中给出答案

【讨论】:

    【解决方案4】:
    int main()
    {   
        int arr[8]={7,2,3,2,4,1,4,6};
        int count[9];
        int total=0;    
    
        memset(count,0, sizeof(count));
    
        for(int i=0;i<8;i++)
            count[arr[i]]++;
    
        for(int k=0;k<9;k++)
        {
            if(k>=2 && k<=5 && count[k]>0 )
            {
                total= total+count[k] ;     
            }
        }
    
        printf("%d:",total);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 2020-10-03
      • 1970-01-01
      • 2014-04-27
      • 1970-01-01
      • 2015-07-28
      • 1970-01-01
      相关资源
      最近更新 更多