我有一个非常庞大的正整数数组,表示某个火车站距离中心的距离,例如:
"false"
火车站S [0]距离市中心10英里。 S在升序顺序中,始终在任何时间点排序,也在算法开始之前排序。只是一直。
我想找一个功能来检查是否存在两个距离恰好为N英里的火车站。
例如: N = 1300会给我真实,因为1500 - 200 = 1300。
第一种方法
迭代S并检查每个元素,如果到另一个元素的距离是N.这给了我两个循环,我猜O(n ^ 2)。我不想要O(n ^ 2),因为数组可能非常庞大,需要更好的性能。
其他方法
我做了很多研究,但我发现只有O(n)是可能的。我希望这个时间复杂。我的解决方案看起来像这样,但遗憾的是它根本无法解决。
true
答案 0 :(得分:3)
只需递增两个指针O(n)
和i
,即可实现线性时间(j
)。您希望i
和j
找到a[j] - a[i] == N
。逻辑很简单:
a[j] - a[i] < N
:增量j
(距离变大)a[j] - a[i] > N
:增量i
(距离变小)这就是全部!在代码中:
int i = 0;
int j = 0;
while ((a[j] - a[i] != N) && j < size) { // size is length of a
if (a[j] - a[i] < N) {
j++;
} else {
i++;
}
}
if (j < size) {
printf("found pair: %d %d\n", i, j);
}
手握正确性证明:原则上,我们应该针对可能提供解决方案的所有a[j]
检查每个a[i]
。也就是说,对于每个j
,我们会检查范围p_j <= i <= q_j
,例如a[j] - a[p_j] > N
和a[j] - a[q_j] < N
。如果存在涉及j
的解决方案,则必须在i
值范围内找到该解决方案。
现在,这个算法几乎可以做到这一点,但有一个例外:有时我们连续多次递增j
,所以我们显然没有在整个范围内检查它。我们再次增加j
,因为a[j] - a[i] < N
。但是,如果发生这种情况,我们也知道a[j] - a[i-1] > N
。我留给你核实这个。
这意味着我们会针对可能提供解决方案的所有j
值范围检查i
。结果是正确的。
我们有两个指针。在每个步骤中,一个指针递增。 2(j
)中较大者的大小由n
限定,因此在O(n)
时间内运行。
答案 1 :(得分:0)
sum
应更改为distance
它应该是:
if(distance < N) {
right--;
left--;
}
不仅仅是
if(distance < N)
right--;
答案 2 :(得分:0)
此代码块中存在错误:
if (distance < N)
right--;
您还希望在此处减少left
的值:
if (distance < N)
{
right--;
left--;
}
此外,第12行中的变量sum
应为distance
。