LC167
两数之和 II · 输入有序数组
左右双指针 · 用有序性安全排除 · O(n) / O(1)
在升序数组 [2,7,11,15] 中找两个不同元素,使其和等于 target=9。 经典命中 2+7=9,返回 1-indexed 下标 [1,2]。
双指针时间 O(n)空间 O(1)
边界测试 · 切换后整段动画会重算
帧 1/4Scene 1
当前步骤
Scene 1:有序数组 · 左右指针就位
非递减数组 [2,7,11,15],target=9。L 指向最小值 2,R 指向最大值 15。接下来用两端之和与 target 比较,依据有序性安全排除不可能元素。
L=0 · R=3 · target=9
为什么正确 · 排除逻辑
数组有序时,[L,R] 闭区间内的任意配对之和,被 a[L]+a[R] 与 a[L]+a[n-1]、a[0]+a[R] 夹住;两端比较能安全收缩候选区。
- 1.sum < target 时:R 指向当前候选区间内的最大值,numbers[L] 与最大值相加仍不够,因此 numbers[L] 不可能参与答案,可安全排除 L 并右移。
- 2.sum > target 时:L 指向当前候选区间内的最小值,numbers[R] 与最小值相加已超标,因此 numbers[R] 不可能参与答案,可安全排除 R 并左移。
- 3.每一步至少排除一个不可能元素;L 只增、R 只减,合计最多移动 n 次,时间 O(n),额外空间 O(1)。
有序数组 · 双指针执行台
target = 9
L
2idx 0
7idx 1
11idx 2
R
15idx 3
L (0-idx)
0
R (0-idx)
3
numbers[L]
—
numbers[R]
—
sum = —
初始化:L=0,R=n-1
代码 · 当前高亮行随帧切换
1func twoSum(numbers []int, target int) []int {2 l, r := 0, len(numbers)-13 for l < r {4 sum := numbers[l] + numbers[r]5 if sum == target {6 return []int{l + 1, r + 1}7 }8 if sum < target {9 l++10 } else {11 r--12 }13 }14 return nil15}
不变量 · 算法为什么对
- · 若存在解,两个下标一定都落在闭区间 [L, R] 内。
- · 有序性是安全排除的前提:被排除的元素不会再参与任何合法配对。
- · 返回 []int{l+1, r+1},LeetCode 要的是 1-indexed。
时间线 · 点击跳转
题目说明 · 四个前提
- ·输入数组是非递减有序数组(升序)。
- ·题目保证恰好存在唯一解。
- ·不能使用同一个元素两次(必须选两个不同下标)。
- ·返回 1-indexed 下标 [l+1, r+1],不是代码里的 0-indexed [l, r]。
最容易错的点
- ✗代码里 l、r 是 0-based,但 LeetCode 要求返回 [l+1, r+1]。
- ✗不要直接 return [l, r] —— 那是 0-indexed,会 WA。
- ✗不要用哈希表当最优解:本题数组有序且要求 O(1) 空间,双指针才是正解。
- ✗数组无序时双指针排除逻辑不成立;LC1 才适合哈希,LC167 的前提是已排序。