1 题目
输入一个递增排序的数组和一个数字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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2 Java
2.1 方法一(双指针,滑动窗口)
class Solution {
public int[] twoSum(int[] nums, int target) {
// 双指针查找,有点似曾相识
int l = 0, r = nums.length - 1;
while(l < r){
int sum = nums[l] + nums[r];
if(sum < target) l++; // 小了是左侧收缩!!!
else if(sum > target) r--;
else if(sum == target) return new int[]{nums[l], nums[r]};
}
return new int[0];
}
}
2.2 方法二(二分查找加速)
对方法一的优化,先通过二分查找找到nums中小于target的区间,r为区间右端
再用双指针
class Solution {
public int[] twoSum(int[] nums, int target) {
if(nums.length < 2) return new int[0];
// 双指针查找,有点似曾相识
int l = 0, r = binary(nums, target);
while(l < r){
int sum = nums[l] + nums[r];
if(sum < target) l++;
else if(sum > target) r--;
else if(sum == target) return new int[]{nums[l], nums[r]};
}
return new int[0];
}
// 二分查找nums里小于target的区间的右端
public int binary(int[] nums, int target){
int l = 0, r = nums.length - 1;
while(l <= r){
int m = (l + r) / 2;
if(nums[m] > target) r = m - 1;
else if(nums[m] < target) l = m + 1;
else if(nums[m] == target) return m - 1;
}
return r;
}
}
2.3 方法三(HashMap数组查找)
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
// 若存在另一半,输出结果
if(map.containsKey(target - nums[i])) return new int[]{i, map.get(target - nums[i])};
// 若不存在,map记录该元素
map.put(nums[i], i);
}
return new int[0];
}
}