【问题标题】:Algorithms - Count all pairs of equal numbers in a sorted array in O(n)?算法 - 在 O(n) 中计算排序数组中的所有相等数字对?
【发布时间】:2017-09-26 12:02:08
【问题描述】:

一个让我猜测的问题如下:

假设我们有一个带有数字 {1,1,1,1,2,2,4,4,4} 的排序数组。

现在,鉴于我们可以清楚地看到我们有六对 1、一对 2 和三对 4(10 对)。你将如何构建一个在 O(n) 中找到这些对的算法?

我有一个算法可以计算数组中的对,这样做是这样的:

Arrays.sort(array);
int counter = 0; 
for(int i = 0; i<array.length; i++) {
     for(int j = i+1; j<array.length; j++) {
          if(j!=i && array[j] == array[i]) {
	counter++;
	}
      }
}
return counter; 

但这在 O(N^2) 中运行,我猜(我是算法的新手)有一个更好的解决方案可以仅使用一个 for 循环或多个 while 循环来获得相同的结果?

我想听听你的想法!

【问题讨论】:

  • “清楚地看到我们在 1 上有六对”
  • 您提到的61 是指4 choose 2 = 6 吗?怎么有22?请详细说明。
  • 很明显你说...
  • 澄清一下 - 假设我们有 ABCD。那么字符的不同组合就是AB、AC、AD、BC、BD、CD。现在,如果你对 1 做同样的事情 - 你会明白我的意思 :)
  • 请注意,原始帖子与帖子的当前编辑版本略有不同。对于“六对一”,OP 确实意味着n choose 2。现在改为“出现数字”,但这会稍微改变问题。

标签: java arrays algorithm sorting


【解决方案1】:

你可以在O(N):

int pairs = 0; 
int times = 1;
for (int i = 1; i < array.length; ++i) {
    if (array[i] == array[i-1]) {
        ++times;
    } else {
        pairs += times*(times-1) / 2;
        times = 1;
    }                   
}
pairs += times*(times-1) / 2;
return pairs;       

可运行:https://ideone.com/mu65ie

对于每个不同的数字,计算其出现次数times。不同对的数量等于选择的数量C(times, 2) = times*(times-1) / 2

【讨论】:

  • 对不起,Dale,评论了错误的代码! :) 您的解决方案是可以很好地找到 1 的解决方案!了解你的困惑伙伴!
【解决方案2】:

好的,这也是我的解决方案:

 int i = 0;
 int pairs = 0;

 while (i < array.length - 1) {
    if(array[i] == array[i + 1]) {
        pairs += 1;
        i += 2;
    } else {
        i++;
    }
 }

当找到一对时,索引会增加 2,这会使遍历速度更快一些。但是复杂度还是O(n)

当然你在数组是sorted之后运行这个。

【讨论】:

  • O(N) 怎么样?
【解决方案3】:

秘诀是停止重复。缓存显示的数据。您可以使用缓存将其减少为 O(nlogn) 问题。

Pairs 的措辞非常含糊,因此以后会通过更多示例来阐明您不知道名称以找到答案的事物。您可以使用组合数学将问题简化为 O(n)。

wikipedia article 读起来有点迟钝,但您要查找的等式在顶部附近:

n! / (k! * (n - k)!)

其中! 表示阶乘数,n 表示要组合的项目数量(4 个 1),k 表示每个组合的项目数量(一对 2)。所以替换这些值:

4! = 24
2! = 2
(4-2)! = 2
4!/(2!2!) = 24/4 = 6

使用这个等式可以将其简化为 O(n)。由于使用了阶乘并对数据集进行了排序,因此您可以通过缓存阶乘调用的结果以供将来调用,从而进一步提高性能。几乎每次查找的阶乘函数的排序输入都会有缓存命中!

如果您使用的是 python 3,则可能不需要缓存,因为它使用比 python 2 更有效的算法来计算阶乘。缓存会减少冗余,但是对于非常大的值可能会产生良好的结果。

缓存(memoization)示例:

import math

class Cache(object):
    memos = dict()

    def factorial(self, n):
         if not n in self.memos:
             self.memos[n] = math.factorial(n)
         return self.memos[n]

【讨论】:

    【解决方案4】:

    怎么样:

        Arrays.sort(array);
        int counter = 0; 
        for(int i = 1; i<array.length; i++) {
            if(array[i] == array[i-1]) {
                counter++;
                ++i;
            }
        }
        return counter;
    

    【讨论】:

      【解决方案5】:

      这是我的做法。希望它会帮助某人:)

      static int foo(int[] ar) {      
          int count = 0;
          Arrays.sort(ar);
          for(int i = 0; i<ar.length-1;i++)
          {
                  if(ar[i] == ar[i+1])
                  {
                      count ++;
                      i++;
                  }
          }
          return count;
      
      }
      

      【讨论】:

        猜你喜欢
        • 2019-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-09
        • 1970-01-01
        • 2017-02-13
        相关资源
        最近更新 更多