剑指 Offer 57. 和为s的两个数字
思路:
实际上是很简单的题目,hashmap是肯定可以解决的,这里直接给出不解释:
public int[] twoSum(int[] nums, int target) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
if (!set.contains(target - num))
set.add(num);
else
return new int[]{num, target - num};
}
return new int[]{};
}
接下来,使用双指针,我自然想到了之前那个思路,先扩张窗口,然后再收缩窗口,所以有:
public int[] twoSum(int[] nums, int target) {//错误 [14,15,16,22,53,60] 76 => [16,60]
int[] res = new int[]{-1,-1};
int i = 0;
int j = 1;
while(j<nums.length){
if(nums[i]+nums[j] == target){
return new int[]{nums[i],nums[j]};
}else if(nums[i]+nums[j] > target){
i++;
}else{
j++;
}
}
return res;
}
但是后来发现是错的,正确测试用例[14,15,16,22,53,60] 76 => [16,60]结果并不对(我输出[-1,-1]),原因就是,首先双指针的本意是两个指针移动的方向对nums[i]+nums[j]造成的结果应该是相反的!!显然如果我们初始化两个指针为0,1位置,那么她两永远只能向右移动,nums[i]+nums[j]永远只能增大,所以这是错的。
因此在这种情况下双指针应该在两侧!!!
正确代码如下:
public int[] twoSum(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left < right) {
int cur = nums[left] + nums[right];
if (cur == target)
return new int[]{nums[left], nums[right]};
else if (cur > target)
right--;
else
left++;
}
return new int[]{};
}
剑指 Offer 57 - II. 和为s的连续正数序列
思路:
然后这一题我又错了。。。因为我又从两端开始移动指针了,然而这次的查找目标为 sum[j]-sum[i],所以指针就应该在一侧移动!!
public int[][] findContinuousSequence(int target) {
List<int[]> res = new ArrayList<>();
int[] sum = new int[target];
for(int i=1;i<target;i++) sum[i] = i + sum[i-1];
int i=0;
int j=2;//不可以从两边
while(j<target){
if(sum[j]-sum[i] == target){
int[] newarr = new int[j-i];
int q = 0;
for(int p=i+1;p<=j;p++){
newarr[q++] = p;
}
res.add(newarr);
j++;
}else if(sum[j]-sum[i] > target){
i++;
}else{
j++;
}
}
int[][] ans = new int[res.size()][];
for(int n=0;n<ans.length;n++) ans[n] = res.get(n);
return ans;
}
当然其实sum数组可以在遍历的时候累加,不用额外去加:
public int[][] findContinuousSequence(int target) {
List<int[]> list = new ArrayList<>();
for (int l = 1, r = 1, sum = 0; r < target; r++) {
sum += r;
while (sum > target) {
sum -= l++;
}
if (sum == target) {
int[] temp = new int[r - l + 1];
for (int i = 0; i < temp.length; i++) {
temp[i] = l + i;
}
list.add(temp);
}
}
int[][] res = new int[list.size()][];
for (int i = 0; i < res.length; i++) {
res[i] = list.get(i);
}
return res;
}