剑指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,返回空数组
- 初始化左右指针
left
和right
,分别指向第一个和最后一个元素 - 循环查找过程:
- 如果左右指针指向的数字之和为target,则返回这两个数字组成的数组
- 如果左右指针指向的数字之和大于target,右指针左移一位,使数字之和减少
- 如果左右指针指向的数字之和小于target,左指针右移一位,使数字之和增加
- 循环结束,还没有找到两个符合要求的数字,则返回空数组
解答
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),只需要两个指针作为辅助变量