查找数组中的对数,其中 A[i] * A[j] > A[i] + A[j]

Posted

技术标签:

【中文标题】查找数组中的对数,其中 A[i] * A[j] > A[i] + A[j]【英文标题】:Finding number of pairs in array where A[i] * A[j] > A[i] + A[j] 【发布时间】:2014-07-17 11:17:39 【问题描述】:

例如如果数组 A 是

A[0] = 0.1
A[1] = 0.6
A[2] = 1.2
A[3] = 1.7
A[4] = 3.5

那么对于 (3,4) 对,我们有 A[3]*A[4] > A[3]+A[4]

我想在一个数组中找到这样对的数量。

还有A[i] = A1 [i] + A2[i]/1,000,000

其中 A1 和 A2 是给定的输入,A1 和 A2 按排序顺序

用 O(n^2) 算法回答是微不足道的。有人告诉我有 O(n) 解决方案,无需使用额外空间。我正在寻找那个。

【问题讨论】:

O(n) 算法查找排序数组中的对数,其中 A[i]*A[j] > A[i] + A[j] 数字是无符号还是有符号? @mch 无符号数 我以为我有一个解决方案,首先是重新排列不等式以给出(A[i] - 1) * (A[j] - 1) > 1,但我能想到的最好的解决方案是O(n log n)。我认为这是正确的开始方式。 你认为的 O(nlogn) 解决方案是什么? 【参考方案1】:
x * y > x + y

除以 x*y(对于正值)

1/x + 1/y < 1

让第一个光标 (R) 指向右侧元素(最小 1/a[i] 值),第二个光标 (L) 指向左侧元素。 将 L 向右移动,直到倒数和达到 1。 将 (R-L) 添加到结果中。 步骤 R 向左。 重复移动L,直到R和L相遇

两个光标最多移动N步,所以算法需要O(N)

【讨论】:

为什么我们需要将 R 步向左?我无法理解那一步。能详细点吗? @Sandeep 寻找更多合适的对 - 当1/a[R]+1/a[L] 超过 1,但 1/a[R-k]+1/a[L+p] 仍小于 1 时【参考方案2】:

由于问题中没有明确说明,因此我将在以下内容中做出以下两个假设:

镜像对只计算一次(否则,如果 (a,b) 是,则 (b,a) 是另一个有效对,因此会增加有效对的数量) 条目不得使用两次(例如,(3.01,3.01) 不是有效对)

这两个假设都可以通过代码的微小变化来改变。

A 已排序,因为 A1A2 已排序。 举个小例子,如下所示

#include <iostream>
#include <vector>

using namespace std;

int main()

   std::vector<double> A(0.1,0.15,0.25,0.29,0.35,0.55,0.65,0.85,1.15,1.44,1.46,1.59,1.88,2.01,2.04,2.05,3.01);
   size_t i=0, j=A.size()-1;
   int result = 0;
   if (A[j] <= 2) return 0;
   while (i != j) 
      if (A[i]*A[j]>A[i]+A[j]) 
        result += j-i;
        cout << A[i] << " to " << A[j] << " for a total of " << result << endl;
        --j;
     else 
        ++i;
    
   
   return 0;

输出 8。http://ideone.com/LaV9Cy

这是O(n),因为A[i+1] &gt; A[i] 有效,因此如果第二个&gt; 成立,则(A[i+1] - 1) * (A[j] - 1) &gt; (A[i] - 1) * (A[j] - 1) &gt; 1。因此,我们可以简单地将我们找到的两个极值 (result += j-i;) 之间的元素数量相加,而不是单独尝试所有这些。

【讨论】:

我也有类似的想法。但是,我使用0.1,0.15,0.25,0.29,0.35,0.55,0.65,0.85,1.15,1.44,1.46,1.59,1.88,2.01,2.04,2.05,3.01 尝试了您的解决方案。不工作。结果应该是 20,但你的结果是 8。 @DavidWallace 好问题。出于某种原因,这对我来说更直观 xD 我可能已经习惯了看到迭代器。你也可以使用ij @gexicide 8 是第一个 += p2-p1 将给出的数字(1.153.01 之间的元素),第二个将给出另外两个(2.01 到 @987654339 @)。如果你想要对称对(因为 (a,b) = (b,a) 有效地计算每对两次)并且你有 20 个,你可以将它乘以 2。 @example:“第二个会给另外两个”是什么意思?简单地复制粘贴您的算法会产生 8,这是错误的。因此,您的代码似乎不包含“第二个”。 我有一个奇怪的怀疑,增加 result 的那一行应该是 result += p2 - p1 + 1; 但我现在不确定 - 因为我对这个问题有很多错误的想法。

以上是关于查找数组中的对数,其中 A[i] * A[j] > A[i] + A[j]的主要内容,如果未能解决你的问题,请参考以下文章

ACM_二维数组的查找

算法设计《分治法》归并排序实例分析之逆序对数

来自两个排序数组的最大对数

2023-03-13:给定一个整数数组 A,坡是元组 (i, j),其中 i < j 且 A[i] <= A[j], 这样的坡的宽度为 j - i。 找出 A 中的坡的最大宽度,如果不存在,返回 0

查找数组中的一个数,并计算此数之前的和

bzoj 3622