剑指 Offer 57. 和为s的两个数字
首先就容易想到的就是暴力,但是我们一看数据范围,\(10^5\)。套\(O(n^2)\)一般来说一定会超时,经过实验也发现确实会超时。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] ans = new int[2];
int n = nums.length;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
if(nums[i] + nums[j] == target) {
ans[0] = nums[i];
ans[1] = nums[j];
return ans;
}
}
}
return null;
}
}
然后比较容易想得到的的办法就是leetcode第一题两数之和的hash法一个已出现的值,再看是否右另外一个。
class Solution {
public int[] twoSum(int[] nums, int target) {
// int[] ans = new int[2];
int n = nums.length;
Set<Integer> set = new HashSet<>();
for(var num : nums) {
if(set.contains(target - num)) {
return new int[]{num, target - num};
}
set.add(num);
}
return null;
}
}
但是这些都并不是最优解,因为都忽略了题目给出的升序数组的条件,因为我们可以使用双指针法来求解问题。
设置两个指针l和r,l指向开头,r指向结尾,若l与r之和大于所求target,说明需要使两数和小一些,r左移,若小于,需要使两数之和大一些,l右移。
class Solution {
public int[] twoSum(int[] nums, int target) {
int n = nums.length, l = 0, r = n - 1;
while(l < r) {
int sum = nums[l] + nums[r];
if(sum == target) {
return new int[]{nums[l], nums[r]};
} else if(sum > target) {
r--;
} else if(sum < target) {
l++;
}
}
return null;
}
}