二分查找你学废了吗?快来看看这道题如何使用二分查找解决吧!
LeetCode链接:167. 两数之和 II - 输入有序数组
1.题目描述
给你一个下标从 1 开始的整数数组 numbers
,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target
的两个数。如果设这两个数分别是 numbers[index1]
和 numbers[index2]
,则 1 <= index1 < index2 <= numbers.length
。
以长度为 2 的整数数组 [index1, index2]
的形式返回这两个整数的下标 index1
和 index2
。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
示例 1:
1 2 3
| 输入:numbers = , target = 9 输出: 解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 。
|
示例 2:
1 2 3
| 输入:numbers = , target = 6 输出: 解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 。
|
示例 3:
1 2 3
| 输入:numbers = [-1,0], target = -1 输出:[1,2] 解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
|
提示:
- $2 <= numbers.length <= 3 * 10^4$
-1000 <= numbers[i] <= 1000
numbers
按 非递减顺序 排列
-1000 <= target <= 1000
- 仅存在一个有效答案
2.题解
- 这道题目是1. 两数之和的变体,其解题方法均可以用在该方法上,但是并没有利用这道题目的特性:数组为 非递减顺序排列
- 二分查找的时间复杂度$O(nlog(n))$
- 双指针的时间复杂度$O(n)$
2.1 二分查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Solution { public int[] twoSum(int[] numbers, int target) { for (int i = 0; i < numbers.length; i++) { int newTarget = target - numbers[i]; int left = i + 1, right = numbers.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (numbers[mid] == newTarget) { return new int[] { i + 1, mid + 1 }; } else if (numbers[mid] < newTarget) { left = mid + 1; } else { right = mid - 1; } } } return new int[] { -1, -1 }; } }
|
2.2 双指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Solution { public int[] twoSum(int[] numbers, int target) { int left = 0, right = numbers.length - 1;
while (left <= right) { int sum = numbers[left] + numbers[right];
if (sum > target) { right--; } else if (sum < target) { left++; } else { return new int[] { left + 1, right + 1 }; } }
return new int[] { -1, -1 }; } }
|