NeetCode 11. Two Integer Sum II

https://neetcode.io/problems/two-integer-sum-ii/question?list=neetcode150

ソート済みの配列から、足して target になる2つの添字(1 始まり)を返す。

ソート済みなら、和が目標より大きいか小さいかが「どちらの端を動かすか」をそのまま教えてくれる。

class Solution {
    // 例: numbers = [1, 2, 3, 4], target = 3  ->  [1, 2]
    twoSum(numbers: number[], target: number): number[] {
        let l = 0;
        let r = numbers.length - 1;

        // すれ違ったら終わり。同じ要素は2回使えないので l < r(l <= r ではない)
        while (l < r) {
            const sum = numbers[l] + numbers[r];

            if (sum > target) r--;      // 大きすぎる -> 右端をひとつ小さい値へ
            else if (sum < target) l++; // 小さすぎる -> 左端をひとつ大きい値へ
            else return [l + 1, r + 1]; // 1 始まりなので +1
        }

        return [];
    }
}

よくある間違い: r を巻き戻す

l を for で回し、l が進むたびに r を右端へ戻す書き方は、動くがすべてのペアを試す二重ループになっていて O(n²)。捨てた候補を拾い直している時点で、two pointers ではなく総当たり。ポインタは戻さないのが型。