leetcode-167. 两数之和 II-输入有序数组

双指针法


题目详情

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] numbers[index2] ,则 1 <= index1 < index2 <= numbers.length
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1index2
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。


示例1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:27 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2]

示例2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:24 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3]

示例3:

输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-10 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2]

我的代码:

C++

class Solution 
{
public:
    vector<int> twoSum(vector<int>& numbers, int target) 
    {
        int left=0,right=numbers.size()-1,sum;
        while(left<right)
        {   sum=numbers[left]+numbers[right];
            if(sum==target)
            break;
            if(sum<target)
            ++left;
            else
            --right;
        }
        return vector<int>{left+1,right+1};
    }
};

Java

class Solution {
    public int[] twoSum(int[] numbers, int target) {

        int left = 0, right = numbers.length-1, sum = 0;

        while (left < right){

            sum = numbers[left] + numbers[right];
            if (sum == target) break;

            if (sum < target) ++left;
            else --right;
            
        }

        return new int[]{left + 1, right + 1};

    }
}

涉及知识点:

1.双指针算法

双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。也可以延伸到多个数组的多个指针。
若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索。
若两个指针指向同一数组,但是遍历方向相反,则可以用来进行搜索,待搜索的数组往往是排好序的。

思路:

因为数组已经排好序,我们可以采用方向相反的双指针来寻找这两个数字,一个初始指向最小的元素,即数组最左边,向右遍历;一个初始指向最大的元素,即数组最右边,向左遍历。
如果两个指针指向元素的和等于给定值,那么它们就是我们要的结果。如果两个指针指向元素的和小于给定值,我们把左边的指针右移一位,使得当前的和增加一点。如果两个指针指向元素的和大于给定值,我们把右边的指针左移一位,使得当前的和减少一点。

原因:
可以证明,对于排好序且有解的数组,双指针一定能遍历到最优解。
证明方法如下:假设最优解的两个数的位置分别是 l 和 r。
我们假设在左指针在 l 左边的时候,右指针已经移动到了 r;此时两个指针指向值的和小于给定值,因此左指针会一直右移直到到达 l。
同理,如果我们假设在右指针在 r 右边的时候,左指针已经移动到了 l;此时两个指针指向值的和大于给定值,因此
右指针会一直左移直到到达 r。
所以双指针在任何时候都不可能处于 (l,r) 之间,又因为不满足条件时指针必须移动一个,所以最终一定会收敛在 l 和 r。

posted @ 2022-03-24 19:25  ggaoda  阅读(6)  评论(0编辑  收藏  举报  来源