(i, j)
对,要么是被计算过,要么是可证明小于某个已计算过的 S(i, j)
,那么我们可以说这一次指针移动是安全的。(i, j) = (0, n - 1)
,那么该状态将计算 S(0, n - 1)
。
H[0] < H[n - 1]
,那么将消去 (0, 1), (0, 2), ..., (0, n)
等 n - 1
个状态。H[0] > H[n - 1]
,那么将消去 (0, n - 1), (1, n - 1), ..., (n - 2, n - 1)
等 n - 1
个状态。定义消去集为 X
,待解集 R
,R_i = R_{i-1} - X
。
算法的初始状态,待解集合 R = {(i, j), 0 <= i < j <= n - 1}
,而正确状态一定位于 R
中。因此,初始状态是安全的。
k
个状态是安全的,那么完成移动小指针操作得到的第 k+1
个状态也是安全的从状态 k
到状态 k+1
,算法完成了一次消去操作。
H[i] < H[j]
时,完成的是消去 X = {(i, i + 1), (i, i + 2), ..., (i, j)}
。对于任意 (i, j') ∈ X
,我们有:
H[i] < H[j']
,那么 S(i, j') = H[i] * (j' - i) < H[i] * (j - i) = S(i, j)
,所以 X
中的状态都小于 S(i, j)
。H[i] >= H[j']
,那么 S(i, j') = H[j'] * (j' - i) <= H[i] * (j' - i) < H[i] * (j - i) = S(i, j)
,所以 X
中的状态都小于 S(i, j)
。因此,当 H[i] < H[j]
时,从 R
中消去 X
集合是安全的。
如果 H[i] >= H[j]
,其实是与情形 1 对称的,边界等于归到任意一边不影响。
设 X = (i, j), (i + 1, j), ..., (j - 1, j)
。考虑 (i', j)
:
H[i'] < H[j]
,那么 S(i', j) = H[i'] * (j - i') < H[j] * (j - i') < H[j] * (j - i) = S(i, j)
。H[i'] >= H[j]
,那么 S(i', j) = H[j] * (j - i') < H[j] * (j - i) = S(i, j)
。因此,当 H[i] >= H[j]
时,从 R
中消去 X
集合是安全的。
由 1 和 2 可知,从 R
中消去 X
是安全的。
因此,算法的任一状态都是安全的,证明了双指针法的正确性。
class Solution:
def maxArea(self, height: List[int]) -> int:
length = len(height)
head, tail = 0, length - 1
maximum = 0
while head != tail:
if height[head] < height[tail]:
maximum = max(maximum, height[head] * (tail - head))
head += 1
else:
maximum = max(maximum, height[tail] * (tail - head))
tail -= 1
return maximum