剑指Offer_#57_和为s的两个数字

剑指Offer_#57_和为s的两个数字

Contents

题目

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]

示例 2:

输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]

限制:

1 <= nums.length <= 10^5
1 <= nums[i] <= 10^6

思路分析

这一题是two sum的一个变式,题目与two sum唯一的区别在于,这里输入的数组nums是有序的。那么就不需要像two sum那样使用双重循环或者哈希表来解决,可以采用类似于二分查找的思路。
算法流程

  1. 特殊处理:输入数组长度是1,返回空数组
  2. 初始化左右指针leftright,分别指向第一个和最后一个元素
  3. 循环查找过程:
    • 如果左右指针指向的数字之和为target,则返回这两个数字组成的数组
    • 如果左右指针指向的数字之和大于target,右指针左移一位,使数字之和减少
    • 如果左右指针指向的数字之和小于target,左指针右移一位,使数字之和增加
  4. 循环结束,还没有找到两个符合要求的数字,则返回空数组

解答

class Solution {
    public int[] twoSum(int[] nums, int target) {
        //数组长度是1,则不可能找出两个元素,直接返回空数组
        if(nums.length == 1) 
            return new int[]{};
        int left = 0;
        int right = nums.length - 1;
        while(left < right){
            if(nums[left] + nums[right] == target)
                return new int[]{nums[left],nums[right]};
            else if(nums[left] + nums[right] > target)
                right--;
            else if(nums[left] + nums[right] < target)
                left++;
        }
        //循环结束,还没有返回,说明找不到符合要求的两个数
        return new int[]{};
    }
}

复杂度分析

时间复杂度:O(n),遍历数组一次即可
空间复杂度:O(1),只需要两个指针作为辅助变量

posted @ 2020-07-25 22:57  Howfar's  阅读(129)  评论(0编辑  收藏  举报