「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战」。
前言
给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素
解题思路
- 二分法应该是常见的思路。非递减排列就是增量排序。首先是边界和判定,如果不相同则左侧和二中侧数据和大于我们约定值,则右侧挪向中间,否则左侧移动。
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; ++i) {
int left = i + 1, right = numbers.length - 1;
while (left <= right) {
int mid = (right - left) / 2 + left;
if (numbers[mid] == target - numbers[i]) {
return new int[]{i + 1, mid + 1};
} else if (numbers[mid] > target - numbers[i]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
}
return new int[]{-1, -1};
}
}
小结
- 我们应该注意的是此题很局限,首先是有序递增的。并且最终有且仅会有一组数据成功。所以我们的二分法才会有效。之前我们刷leetcode应该都注意到往往二分法和双指针是并存的。二分法可以解决的事情双指针也是可以的。
- 令左指针l = 0,右指针r = numbers.size() - 1,当l < r 进行循环
- 当numbers[l] + numbers[r] == target时满足条件,退出循环
- 若numbers[l] + numbers[r] > target 说明两数和太大,将右指针左移
- 若numbers[l] + numbers[r] < target 说明两数和太小,将左指针右移
int l = 0,r = numbers.size() - 1,sum;
while(l < r){
sum = numbers[l] + numbers[r];
if(sum == target) break;
if(sum < target) l++;
else r--;
}
return {l+1,r+1};
总结
- 两数之和可以看成是两数搭配,暴力破解也会成功。人生也是如此一直等待值得你等待的人。