【问题标题】:count no. of pairs such that absolute difference is less than K数数对,使得绝对差小于 K
【发布时间】:2014-07-12 05:26:56
【问题描述】:

给定一个大小为 N 的数组 A,我如何计算对的数量(A[i]A[j]),以使它们之间的绝对差小于或等于 K,其中 K 是任何正自然数? (ij<=Ni!=j

我的做法:

  1. 对数组进行排序。

  2. 创建另一个数组来存储两个连续数字之间的绝对差。

我是否朝着正确的方向前进?如果是,那我该如何继续?

【问题讨论】:

  • 数组A的大小是多少?如果不是太大,可以for (i=0;i<size;i++) for (j=i+1; j<size;j++) if (abs(A[i]-A[j])<=K) res++;
  • 数组的大小接近10^6。我之前尝试过朴素的算法,但需要很长时间。我需要一个高效的算法。

标签: algorithm counting


【解决方案1】:

这是一个 O(nlogn) 算法:-

1. sort input
2. traverse the sorted array in ascending order.
3. for A[i] find largest index A[j]<=A[i]+k using binary search.
4. count = count+j-i
5. do 3 to 4 all i's

时间复杂度:-

Sorting : O(n)
Binary Search : O(logn)
Overall : O(nlogn)

【讨论】:

  • 排序需要 nlogn
【解决方案2】:

这是 O(n^2):

Sort the array  
For each item_i in array,
  For each item_j in array such that j > i
      If item_j - item_i <= k, print (item_j, item_i)
      Else proceed with the next item_i

【讨论】:

  • 谢谢,但我希望算法的复杂度为 O(nlogn) 或 O(n)。
  • @typedef,我认为我们需要打印这些对,在这种情况下,我认为您无法做到 O(nlgn)。
【解决方案3】:

您的方法部分正确。您首先对数组进行排序。然后保留两个指针i和j。

1. Initialize i = 0, j = 1.  
2. Check if A[j] - A[i] <= K.   
   - If yes, then increment j,  
   - else
       - **increase the count of pairs by C(j-i,2)**. 
       - increment i.
       - if i == j, then increment j.  
3. Do this till pointer j goes past the end of the array. Then just add C(j-1,2) to the count and stop.

通过 i 和 j,您基本上是在维护一个窗口,其中元素之间的差异为

编辑:这是基本思想,您必须检查边界条件。此外,您还必须跟踪添加到计数中的过去间隔。您需要减去当前间隔的重叠以避免重复计算。

复杂度:O(NlogN),对于排序操作,对于数组遍历是线性的

【讨论】:

  • 投反对票的人,请告诉我出了什么问题。如有需要会更正。
  • 我认为将其表达为:对于每个 i,将 j 向上移动到 A[j] - A[i] > K(或 j=N)的点,然后添加 j-i- 1 到计数。
  • @typedef 是的,C 表示组合。
  • @Anonymous,不,我们需要增加 i 和 j 之间所有可能的对。
  • 我不相信这会返回正确的结果,也不清楚当 j 从数组末尾掉线时该怎么办。测试用例:[0, 1, 2, 3, 4, 5],K=10。
【解决方案4】:

对数组进行排序后,您可以在 O(N) 时间内计算总和。

这里有一些代码。 O(N) 算法是pair_sums,pair_sums_slow 显然是正确的,但是O(N^2) 算法。我在最后运行了一些测试用例,以确保两种算法返回相同的结果。

def pair_sums(A, k):
    A.sort()
    counts = 0
    j = 0
    for i in xrange(len(A)):
        while j < len(A) and A[j] - A[i] <= k:
            j+=1
        counts += j - i - 1
    return counts

def pair_sums_slow(A, k):
    counts = 0
    for i in xrange(len(A)):
        for j in xrange(i+1, len(A)):
            if A[j] - A[i] <= k:
                counts+=1
    return counts

cases = [
    ([0, 1, 2, 3, 4, 5], 10),
    ([0, 0, 0, 0, 0], 1),
    ([0, 1, 2, 4, 8, 16], 9),
    ([0, -1, -2, 1, 2], 2)
]

for A, k in cases:
    want = pair_sums_slow(A, k)
    got = pair_sums(A, k)
    if want != got:
        print A, k, want, got

pair_sums 背后的想法是,对于每个 i,我们找到最小的 j,使得 A[j] - A[i] > K(或 j=N)。那么 j-i-1 就是以 i 为第一个值的对数。

由于数组已排序,j 只会随着 i 的增加而增加,因此整体复杂度是线性的,因为尽管存在嵌套循环,但内部操作 j+=1 最多可发生 N 次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多