前言
对撞指针常用作有序数组的元素查找,使用两个指针分别从头尾往中间进行迭代,相遇时终止。
刚接触对撞指针时,笔者对其算法原理有些怀疑:由于这两个指针不能“后退”,如何确保在迭代时,不错过有效值呢?下面尝试给与一些数学证明,以供理解。
证明
如图,设ab值为有序数组N中存在的两个有效值,即:
a
+
b
=
t
a
r
g
e
t
(1)
a + b = target \tag{1}
a+b=target(1)
现在证明,对撞指针从两端往中间迭代时,左指针不会错过a值,右指针不会错过b值。
设a值的左边界L1,b值的右边界L2,设数组N为递增数组,处于左边界的任意值
x
x
x存在:
x
<
a
i
f
x
<
L
1
(2)
x < a \quad if \quad x<L1\tag{2}
x<aifx<L1(2)
同理,右边界
y
y
y,
y
>
b
i
f
y
>
L
2
(3)
y > b \quad if \quad y>L2 \tag{3}
y>bify>L2(3)
按照算法原理,左右指针会分别从末端往a, b值“收缩”,假设初始值(即双指针处于数组的左右末端时)
x
+
y
>
t
a
r
g
e
t
x + y > target
x+y>target, 结合上式,直接把x < a和y > b代入,可得:
(
<
a
)
+
(
>
b
)
>
t
a
r
g
e
t
(4)
(<a)+(>b) > target \tag{4}
(<a)+(>b)>target(4)
按照算法原理,由于此时值大于
t
a
r
g
e
t
target
target,右指针需要左移,而结合公式(1)(3)(4),有:
(
<
a
)
+
b
<
t
a
r
g
e
t
(<a) + b < target
(<a)+b<target
所以可以推出,在右指针左移的过程中,一定会在到达有效值b时(或之前),当前值小于target,使左移停止,所以,右指针不会越过有效值b,左指针同理。