双指针可以解决2-sum问题的数学证明

2021-09-09  本文已影响0人  摇摆苏丹

设存在长度为n的升序数列x_{0},x_{1},x_{2}\ldots x_{n-1}\boldsymbol{x},设一个目标值为t,假设唯一存在一对x_{i},x_{j}\in \boldsymbol{x},即x_{0} \leq x_{i} \lt x_{j} \leq x_{n-1},使得x_{i}+x_{j}=t

要求证明双指针算法可以在x_{i},x_{j}存在的时候找到这对值。

双指针算法的Java描述如下:

import java.util.ArrayList;
import java.util.List;

public class Main {

    public static List<Integer> solveTwoSum(List<Integer> list, Integer target) {
        // compare的语法自从java7开始支持
        // lambda表达式的语法自从java8开始支持
        list.sort((a, b) -> Integer.compare(a, b));
        // System.out.println(list);
        Integer left = 0;
        Integer right = list.size() - 1;
        while (left < right) {
            Integer tmp = list.get(left) + list.get(right);
            if (tmp < target) {
                left += 1;
            } else if (tmp > target) {
                right -= 1;
            } else {
                return List.of(left, right);
            }
        }
        return List.of(-1, -1);
    }

    public static void main(String[] args) {
        // List.of的语法自从java9开始支持
        List<Integer> list = new ArrayList<>();
        List<Integer> ans;
        Integer target;

        list.clear();
        list.addAll(List.of(1, 2, 3));
        target = 5;
        ans = solveTwoSum(list, target);
        System.out.println(ans);

        list.clear();
        list.addAll(List.of(1, 2, 4, 8, 16, 32));
        target = 25;
        ans = solveTwoSum(list, target);
        System.out.println(ans);
    }
}

证明:

设左指针右移操作为A,设右指针左移操作为B,那么双指针算法会在最多n-1次操作之内找到x_{i},x_{j}。显然x_{i},x_{j}包含在x_{i-1},x_{j}之中,或包含在x_{i},x_{j+1}之中,对于这两种情况,分别经过一次A操作与一次B操作之后可以找到x_{i},x_{j}。同理,x_{i-1},x_{j}也包含在x_{i-2},x_{j}或者x_{i-1},x_{j+1}中,对于这两种情况,分别经过一次A操作与一次B操作之后可以找到x_{i-1},x_{j}。以此类推,经过多次A操作或者B操作之后,总能找到x_{i},x_{j}

上一篇 下一篇

猜你喜欢

热点阅读