剑指 Offer 57. 和为s的两个数字
输入一个递增排序的数组和一个数字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
一、二分查找+双指针
这个二分查找+双指针的方法有点长,但可以为更简便的代码提供一点思路。
class Solution {
public int[] twoSum(int[] nums, int target) {
//执行二分查找
int index = binarySearch(nums,target);
int i = 0;
while (i < index) {
//target - nums[i] > nums[index] 等价于nums[i] + nums[index] < target是为了防止内存溢出
while (i < index && target - nums[i] > nums[index]) {
i++;
}
while (i < index && target - nums[i] < nums[index]) {
index--;
}
if (target - nums[i] == nums[index]) {
return new int[] {nums[i],nums[index]};
}
}
return new int[0];
}
int binarySearch(int[] nums, int target) {
//二分查找主要是为了设定一个范围,最后让i和index查找和为s的两个数字
int i = 0, j = nums.length - 1;
while (i < j) {
//int mid = (i + j) / 2; 等价于int mid = i + ((j - i) >> 1);
int mid = i + ((j - i) >> 1);
if (nums[mid] > target) {
j = mid - 1;
} else {
i = mid + 1;
}
}
return j;
}
}
二、双指针
这个是K神的思路:
循环搜索: 当双指针相遇时跳出;
1.计算和 s = nums[i] + nums[j] ;
2.若 s > targets>target ,则指针 j 向左移动,即执行 j = j - 1;
3.若 s < targets<target ,则指针 i向右移动,即执行 i = i + 1 ;
4.若 s = targets=target ,立即返回数组 [nums[i], nums[j]] ;
class Solution {
public int[] twoSum(int[] nums, int target) {
int i = 0, j = nums.length - 1;
while(i < j) {
int s = nums[i] + nums[j];
if(s < target) i++;
else if(s > target) j--;
else return new int[] { nums[i], nums[j] };
}
return new int[0];
}
}
参考链接: