LeetCode167_两数之和 Ⅱ - 输入有序数组
- 标签:#数组 #双指针 #二分查找
- Ⅰ. 题目
- Ⅱ. 示例
- 0. 个人方法
- 官方题解一:二分查找
- 官方题解二:双指针
标签:#数组 #双指针 #二分查找
Ⅰ. 题目
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
Ⅱ. 示例
· 示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
· 示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
· 示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
0. 个人方法
使用双指针进行从前往后和从后往前的查找。
class Solution {
public:vector<int> twoSum(vector<int>& numbers, int target) {int length = numbers.size();int ans = 0;std::vector index(2, 1);for (int i=0; i<length; ++i){ans = numbers[i];for (int j=length-1; j>=0; j--){ans += numbers[j];if (ans == target){index[0] += i;index[1] += j;return index;}else{ans = numbers[i];}if (numbers[j] < target - numbers[i])break;}}return index;}
};
官方题解一:二分查找
在数组中找到两个数,使得它们的和等于目标值,可以首先固定第一个数,然后寻找第二个数,第二个数等于目标值减去第一个数的差。利用数组的有序性质,可以通过二分查找的方法寻找第二个数。为了避免重复寻找,在寻找第二个数时,只在第一个数的右侧寻找。
class Solution {
public:vector<int> twoSum(vector<int>& numbers, int target) {for (int i = 0; i < numbers.size(); ++i) {int low = i + 1, high = numbers.size() - 1;while (low <= high) {int mid = (high - low) / 2 + low;if (numbers[mid] == target - numbers[i]) {return {i + 1, mid + 1};} else if (numbers[mid] > target - numbers[i]) {high = mid - 1;} else {low = mid + 1;}}}return {-1, -1};}
};
-
复杂度分析
-
时间复杂度:O(nlogn),其中 n 是数组的长度。需要遍历数组一次确定第一个数,时间复杂度是 O(n),寻找第二个数使用二分查找,时间复杂度是 O(logn),因此总时间复杂度是 O(nlogn)。
-
空间复杂度:O(1)。
-
官方题解二:双指针
class Solution {
public:vector<int> twoSum(vector<int>& numbers, int target) {int low = 0, high = numbers.size() - 1;while (low < high) {int sum = numbers[low] + numbers[high];if (sum == target) {return {low + 1, high + 1};} else if (sum < target) {++low;} else {--high;}}return {-1, -1};}
};
-
复杂度分析
-
时间复杂度:O(n),其中 n 是数组的长度。两个指针移动的总次数最多为 n 次。
-
空间复杂度:O(1)。
-