两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O ( n 2 ) O(n^2) O(n2) 的算法吗?
枚举法
双重for循环,依次从头查找和为target的两数。
注意 j 的取值范围,因为每一个元素不能被使用两次,而 i 前的数已经参与匹配,所以 j 取值范围是range(i+1, len(nums))
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 时间复杂度太高
for i in range(len(nums)):
for j in range(i+1, len(nums)):
if nums[i] + nums[j] == target:
return [i,j]
s = new Solution()
s.twoSum([2, 7, 11, 15], 17)
时间复杂度: O ( N 2 ) O(N^2) O(N2)
空间复杂度: O ( 1 ) O(1) O(1)
简单优化
将对 j 的循环遍历转为在列表切片中查找目标值
# 中等偏下
for i in range(len(nums)):
num_sub = target - nums[i]
if num_sub in nums[i+1:]:
# 将i替换为其他值,避免两次使用同一个数,如:3+3=6
nums[i] = ['']
return [i, nums.index(num_sub)]
时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( 1 ) O(1) O(1)
HashTable实现
力扣官方视频讲解
链接:https://leetcode-cn.com/problems/two-sum/solution/liang-shu-zhi-he-by-leetcode-solution/
哈希表的特点:
- 索引速度快:
hashMap.containsKey()
、hashMap.put()
时间复杂度低
class Solution {
public int[] twoSum(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return new int[0];
}
int len = nums.length;
Map<Integer, Integer> hashMap = new HashMap<>(len);
hashMap.put(nums[0], 0);
for (int i = 1; i < len; i++) {
int num_sub = target - nums[i];
if (hashMap.containsKey(num_sub)){
return new int[]{hashMap.get(num_sub), i};
}
hashMap.put(nums[i], i);
}
return new int[0];
}
}
public class TwoSum {
public static void main(String[] args){
Solution s = new Solution();
int[] arr = new int[]{2, 7, 11, 15};
int target = 9;
int[] result_arr = sts.twoSum(arr, target);
System.out.println(result_arr);
}
}
python语言描述
# 时间复杂度好,空间换时间
hashTable = dict()
# 枚举 enumerate
for i, num in enumerate(nums):
if target - num in hashTable:
return [hashTable[target - num], i]
hashTable[nums[i]] = i
return []
时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( N ) O(N) O(N),主要为哈希表的开销。
HashTable实现–优化
上述基于HashTable
的代码是从左到右依次遍历,最坏的时间复杂度为
O
(
N
)
O(N)
O(N),因此以下代码从两端同时遍历匹配,最坏的情况是中间为目标元素,时间可以减少一半。
Map<Integer, Integer> hashTable = new HashMap<Integer, Integer>();
for (int left = 0, right = nums.length-1; left <= right ; left++, right--) {
if (hashTable.containsKey(target-nums[left])){
return new int[]{hashTable.get(target - nums[left]) ,left};
}
hashTable.put(nums[left], left);
if (hashTable.containsKey(target - nums[right])){
return new int[]{hashTable.get(target - nums[right]), right};
}
hashTable.put(nums[right], right);
}
return new int[0];
参考自力扣:
作者:lyu571
链接:https://leetcode-cn.com/problems/two-sum/solution/1-liang-shu-zhi-he-by-lyu571-0rj5/
同类题目
作者:tangweiqun
链接:https://leetcode-cn.com/problems/two-sum/solution/zhu-jian-you-hua-yi-zhi-dao-zui-you-pei-sexli/