中文题目
给定一个已按照 升序排列 的整数数组 numbers
,请你从数组中找出两个数满足相加之和等于目标数 target
。
函数应该以长度为 2
的整数数组的形式返回这两个数的下标值。numbers
的下标 从 0 开始计数 ,所以答案数组应当满足 0 <= answer[0] < answer[1] < numbers.length
。
假设数组中存在且只存在一对符合条件的数字,同时一个数字不能使用两次。
示例 1:
输入:numbers = [1,2,4,6,10], target = 8 输出:[1,3] 解释:2 与 6 之和等于目标数 8 。因此 index1 = 1, index2 = 3 。
示例 2:
输入:numbers = [2,3,4], target = 6 输出:[0,2]
示例 3:
输入:numbers = [-1,0], target = -1 输出:[0,1]
提示:
2 <= numbers.length <= 3 * 104
-1000 <= numbers[i] <= 1000
numbers
按 递增顺序 排列-1000 <= target <= 1000
- 仅存在一个有效答案
注意:本题与主站 167 题相似(下标起点不同):https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/
通过代码
高赞题解
1. 题目讲解
如果你已经理解了题目,这个视频可以跳过
2. 方案一:二分查找,请看视频:
代码如下:
[]// 时间复杂度:O(nlogn) // 空间复杂度:O(1) public int[] twoSum(int[] nums, int target) { if (nums == null || nums.length == 0) return new int[0]; for (int i = 0; i < nums.length; i++) { int x = nums[i]; // 线性查找 - O(n) // 1. 二分查找 - O(logn) // [i + 1, nums.length - 1] 区间二分查找 target - x int index = binarySearch(nums, i + 1, nums.length - 1, target - x); if (index != -1) { return new int[]{i, index}; } } return new int[0]; } private int binarySearch(int[] nums, int left, int right, int target) { while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; if (nums[mid] > target) right = mid - 1; else left = mid + 1; } return -1; }
[]public: // 二分查找 // 时间复杂度:O(nlogn) // 空间复杂度:O(1) vector<int> twoSum1(vector<int>& numbers, int target) { for (int i = 0; i < numbers.size(); i++) { int x = numbers[i]; // 线性查找 - O(n) // 1. 二分查找 - O(logn) // [i + 1, numbers.length - 1] 区间二分查找 target - x int index = binarySearch(numbers, i + 1, numbers.size() - 1, target - x); if (index != -1) { return {i, index}; } } return {}; } int binarySearch(vector<int>& nums, int left, int right, int target) { while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; if (nums[mid] > target) right = mid - 1; else left = mid + 1; } return -1; }
[]# 二分查找 # 时间复杂度:O(nlogn) # 空间复杂度:O(1) def twoSum1(self, numbers: List[int], target: int) -> List[int]: for i in range(len(numbers)): x = numbers[i] # 1. 二分查找 - O(logn) # [i + 1, nums.length - 1] 区间二分查找 target - x index = self.binary_search(numbers, i + 1, len(numbers) - 1, target - x) if index != -1: return [i, index] return [] def binary_search(self, numbers: List[int], left: int, right: int, target: int) -> int: while left <= right: mid = left + (right - left) // 2 if target == numbers[mid]: return mid elif target > numbers[mid]: left = mid + 1 else: right = mid - 1 return -1
[]// 二分查找 // 时间复杂度:O(nlogn) // 空间复杂度:O(1) var twoSum1 = function(numbers, target) { for (let i = 0; i < numbers.length; i++) { const x = numbers[i] const index = binarySearch(numbers, i + 1, numbers.length - 1, target - x) if (index != -1) { return [i, index] } } return [] }; var binarySearch = function(number, left, right, target) { while (left <= right) { const mid = left + Math.floor((right - left) / 2) if (target == number[mid]) { return mid; } else if (target < number[mid]) { right = mid - 1 } else { left = mid + 1 } } return -1 }
[]// 方法一:严格的二分查找 // 时间复杂度:O(nlogn) // 空间复杂度:O(1) func twoSum1(numbers []int, target int) []int { for i := range numbers { var x = numbers[i] // 线性查找 - O(n) // 1. 二分查找 - O(logn) // [i + 1, nums.length - 1] 区间二分查找 target - x var index = binarySearch(numbers, i + 1, len(numbers) - 1, target - x) if index != -1 { return []int{i + 1, index + 1} } } return []int{} } func binarySearch(numbers []int, left int, right int, target int) int { for left <= right { var mid = left + (right - left) / 2 if numbers[mid] == target { return mid } else if numbers[mid] > target { right = mid - 1 } else { left = mid + 1 } } return -1 }
3. 方案二:双指针, 请看视频:
代码如下:
[]// 时间复杂度:O(n) // 空间复杂度:O(1) public int[] twoSum(int[] nums, int target) { if (nums == null || nums.length == 0) return new int[0]; int left = 0; int right = nums.length - 1; while (left < right) { int sum = nums[left] + nums[right]; if (sum == target) { return new int[]{left, right}; } else if (sum < target) { left++; } else { right--; } } return new int[0]; }
[]public: // 双指针 // 时间复杂度:O(n) // 空间复杂度:O(1) vector<int> twoSum(vector<int>& numbers, int target) { int left = 0, right = numbers.size() - 1; while (left < right) { int sum = numbers[left] + numbers[right]; if (sum == target) { return {left, right}; } else if (sum < target) { left++; } else { right--; } } return {}; }
[]# 双指针 # 时间复杂度:O(n) # 空间复杂度:O(1) def twoSum(self, numbers: List[int], target: int) -> List[int]: left, right = 0, len(numbers) - 1 while left < right: sum = numbers[left] + numbers[right] if sum == target: return [left, right] elif sum < target: left = left + 1 else: right = right - 1 return []
[]// 双指针 // 时间复杂度:O(n) // 空间复杂度:O(1) var twoSum = function(numbers, target) { let left = 0, right = numbers.length - 1 while (left < right) { const sum = numbers[left] + numbers[right] if (sum == target) { return [left, right] } else if (sum < target) { left++ } else { right-- } } return [] };
[]// 双指针 // 时间复杂度:O(n) // 空间复杂度:O(1) func twoSum(numbers []int, target int) []int { var left, right = 0, len(numbers) - 1 for left < right { var sum = numbers[left] + numbers[right] if sum == target { return []int{left + 1, right + 1} } else if sum < target { left++ } else { right-- } } return []int{} }
类似的题目最好是一起刷,这样可以提高刷题效率:
- leetcode 1 号算法题:两数之和
- leetcode 167 号算法题:两数之和Ⅱ - 输入有序数组
- leetcode 170 号算法题:两数之和Ⅲ - 数据结构设计
- leetcode 653 号算法题:两数之和Ⅳ - 输入 BST
- leetcode 15 号算法题:三数之和
- leetcode 18 号算法题:四数之和
在刷题的时候:
如果你觉得自己数据结构与算法基础不够扎实,那么请点这里,这里包含了一个程序员 5 年内需要的所有算法知识
如果你感觉刷题太慢,或者感觉很困难,或者赶时间,那么请点这里。这里用 365 道高频算法题,带你融会贯通算法知识,做到以不变应万变
回溯、贪心和动态规划,是算法面试中的三大难点内容,如果你只是想搞懂这三大难点内容 请点这里
以上三个链接中的内容,都支持 Java/C++/Python/js/go 五种语言
统计信息
通过次数 | 提交次数 | AC比率 |
---|---|---|
11130 | 17066 | 65.2% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|