LeetCode 167.两数之和Ⅱ 输入有序数组
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。 说明: 返回的下标值(index1 和 index2)不是从零开始的。 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。 示例: 输入: numbers = [2, 7, 11, 15], target = 9 输出: [1,2] 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
解题思路
1.暴力打表,会超时
class Solution { public int[] twoSum(int[] numbers, int target) { for (int i = 0; i < numbers.length; i++) { for (int j = i + 1; j < numbers.length; j++) { if ((numbers[i] + numbers[j]) == target) { return new int[] {i+1, j+1}; } } } throw new IllegalArgumentException("参数不存在!"); } }
2.双指针碰撞(官方解法)
class Solution {
public int[] twoSum(int[] numbers, int target) {
int left = 0;
int right = numbers.length - 1;
while (left < right) {
if ((numbers[left] + numbers[right]) > target) {
right--;
} else if ((numbers[left] + numbers[right]) < target) {
left++;
} else {
return new int[] {left + 1, right + 1};
}
}
throw new RuntimeException("找不到参数");
}
}
时间复杂度O(n),空间复杂度O(1)
3.二分法(来自评论),需要指定二分法起始查询位置,边界值的坑有点大
class Solution { public int[] twoSum(int[] numbers, int target) { for (int i = 0; i < numbers.length; i++) { //通过二分查找target-numbers[i]的位置,需要注意边界值 //二分查找left起始位置应为i+1,否则对于测试用例[1, 2, 3, 4, 4, 9, 56, 90] 8,会出现返回[4,4]的情况 int right = binarySearch(numbers, i + 1, numbers.length - 1, target - numbers[i]); if (right != -1) { return new int[] {i + 1, right + 1}; } } throw new IllegalArgumentException(); } public int binarySearch(int nums[], int left, int right, int target) { while (left <= right) { int mid = (left + right) / 2; if (nums[mid] == target) { return mid; } else if (nums[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; } }
时间复杂度O(n^2),空间复杂度O(1)