一、需求
-
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。
- 如果有多对数字的和等于s,则输出任意一对即可。
二、二分法
2.1 思路分析
- 该题与"两数之和"基本一致,因此可由暴力法、两遍哈希表、一遍哈希表来解决,详情见https://blog.csdn.net/Sruggle/article/details/103748396#%E5%9B%9B%E3%80%81%E4%B8%80%E9%81%8D%E5%93%88%E5%B8%8C%E8%A1%A8
- 但这里涉及的是排序数组,故给出二分法及双指针法;
- 遍历数组中的元素,利用二分法查找target - nums[i]是否在nums数组中,找到之后返回;
2.2 代码实现
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int i = 0; i < nums.length; i++) {
int x = binarySearch(nums,target - nums[i]);
if(x != 0) {
return new int[] {x, nums[i]};
}
}
throw new IllegalArgumentException("No two sum solution");
}
public int binarySearch(int[] nums, int value) {
int left = 0;
int right = nums.length - 1;
int mid = 0;
while(left <= right) {
mid = left + (right - left) / 2;
if(nums[mid] > value) {
right = mid - 1;
} else if(nums[mid] < value){
left = mid + 1;
} else {
return nums[mid];
}
}
return 0;
}
}
2.3 复杂度分析
- 时间复杂度为
,其中N为数组中的元素个数,每一次二分查找消耗
,最坏情况下需要查找
次;
- 空间复杂度为O(1);
三、双指针法
3.1 思路分析
- 该方法利用双指针,i 指向数组首元素,j 指向数组末尾元素,当i <= j时,比较nums[i] + nums[j]与target的大小,若前者大于后者,则 j--,若前者小于后者,则i++,相等则返回对应的数组;
3.2 代码实现
class Solution {
public int[] twoSum(int[] nums, int target) {
int i = 0;
int j = nums.length - 1;
while(i <= j) {
if(nums[i] + nums[j] > target) {
j--;
} else if(nums[i] + nums[j] < target) {
i++;
} else {
return new int[] {nums[i], nums[j]};
}
}
return new int[] {nums[i], nums[j]};
}
}
3.3 复杂度分析
- 时间复杂度为O(N),最坏情况下遍历数组中的所有元素;
- 空间复杂度为O(1);
四、学习地址
作者:Krahets