D

当前:LC167 · 两数之和 II · 输入有序数组 · 首次出现于 Day 4 · 路径:顶栏「56天打卡」→ 点击 LC 题号 → 逐题动画

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. 1.sum < target 时:R 指向当前候选区间内的最大值,numbers[L] 与最大值相加仍不够,因此 numbers[L] 不可能参与答案,可安全排除 L 并右移。
  2. 2.sum > target 时:L 指向当前候选区间内的最小值,numbers[R] 与最小值相加已超标,因此 numbers[R] 不可能参与答案,可安全排除 R 并左移。
  3. 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)-1
3 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 nil
15}

不变量 · 算法为什么对

  • · 若存在解,两个下标一定都落在闭区间 [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 的前提是已排序。