JZ57 和为S的两个数字

113 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情

Day35 2023/02/10

题目链接

难度:简单

题目

输入一个升序数组 array 和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,返回任意一组即可,如果无法找出这样的数字,返回一个空数组即可。

示例1

输入:[1,2,4,7,11,15],15
返回值:[4,11]
说明:返回[4,11]或者[11,4]都是可以的   

示例2

输入:[1,5,11],10
返回值: []
说明:不存在,返回空数组

思路一


根据题目中升序序列的条件,我们可以使用双指针的方法,使用双指针,分别指向数组的首尾元素,然后双指针相向这运动,分别相加每次的两个指针所指的元素,如果等于目标值就找到,如果小于就移动左侧指针,如果大于则移动右侧指针。
具体步骤:

  1. 准备左右双指针,初始时分别指向数组首尾。
  2. 相加两个指针所指元素,如果等于目标值则找到所求元素,若大于目标值,左侧指针移动,小于目标值,右侧指针移动。
  3. 当两个指针相等时,还没有找到,则数组没有满足要求的元素存在。

关键点


  • 当相加后小于目标值,说明我们要寻找更大的元素组合,所以要移动左侧指针,使得相加的值变大。
  • 当相加后大于目标值,说明我们要寻找更小的元素组合,所以要移动右侧指针,使得相加的值变小。

算法实现


c++代码实现-双指针

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        vector<int> res; //待返回数组
        //左右双指针
        int left = 0, right = array.size() - 1; //初始化,分别指向首尾元素
        //对撞双指针
        while(left < right){
            //相加等于sum,找到目标
            if(array[left] + array[right] == sum){
                res.push_back(array[left]);
                res.push_back(array[right]);
                break;
            //和太大,缩小右边
            }else if(array[left] + array[right] > sum)
                right--;
            //和太小,扩大左边
            else
                left++;
        }
        return res;
    }
};

  • 时间复杂度 O(n)O(n) --- 左右指针一起访问了数组的全部元素,n为数组长度
  • 空间复杂度 O(1)O(1) --- 常数级数组,无额外的辅助空间

总结

  • 双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。