题目描述
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
解析
解法一
- 思路:递增排序的数组一般会想到二分查找,和为数字s,可遍历数组元素,查找
s-nums[i]
,一旦找到就退出循环。二分查找的复杂度为O(logN),遍历N个节点,所以总的时间复杂度是O(NlogN),空间复杂度是O(1)。
public int[] twoSum(int[] nums, int target) {
for(int i=0;i<nums.length;i++) {
int key1=nums[i];
int key2 = target-nums[i];
boolean exist = search(key2,nums,i+1);
if(exist) {
return new int[] {key1, key2};
}
}
return new int[0];
}
private boolean search(int key, int[] nums, int i) {
int j = nums.length-1;
while(i<=j) {
int mid=(i+j)/2;
if(key==nums[mid]) return true;
else if(key<nums[mid]) j=mid-1;
else i=mid+1;
}
return false;
}
题解之对撞双指针
- 思路:双指针分别同时从前往后(指针i)、从后往前(指针j)遍历,当二者的和==s,返回;当和>s,j–;当和<s,i++。时间复杂度是O(N),空间复杂度是O(1)
public int[] twoSum(int[] nums, int target) {
int i=0, j=nums.length-1;
while(i<j) {
int sum=nums[i]+nums[j];
if(sum==target) return new int[] {nums[i], nums[j]};
else if(sum>target) j--;
else i++;
}
return new int[0];
}
题解之哈希表法
- 思路:用HashSet存数组的元素,contains方法可以O(1)的复杂度判断set内是否有某个数。时间复杂度是O(N),空间复杂度是O(N)。
public int[] twoSum(int[] nums, int target) {
HashSet<Integer> set = new HashSet<>();
for(int i=0;i<nums.length;i++) {
set.add(nums[i]);
}
for(int num:nums) {
int key = target-num;
if(set.contains(key)) return new int[] {num, key};
}
return new int[0];
}