1. 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
法一:暴力法
遍历每个元素 xx,并查找是否存在一个值与 target - xtarget−x 相等的目标元素。
1 class Solution { 2 public int[] twoSum(int[] nums, int target) { 3 // 暴力法 4 for(int i = 0; i < nums.length; i++){ 5 for(int j = i + 1; j < nums.length; j++){ 6 if(nums[i] + nums[j] == target){ 7 return new int[] {i, j}; 8 } 9 } 10 } 11 return null; 12 } 13 }
复杂度分析
时间复杂度为O(n^2),空间复杂度为O(1)
法二:两次HashMap
思路:
两次HashMap,第一次把所有元素都加入到map中,第二次扫描nums数组,判断互补元素是否存在于Map中,注意该目标元素不能是 nums[i]nums[i] 本身!
1 class Solution { 2 public int[] twoSum(int[] nums, int target) { 3 // 两次HashMap 4 HashMap<Integer, Integer> hashMap = new HashMap<>(); 5 // 第一次把所有元素都加入到map中 6 for(int i = 0; i < nums.length; i++){ 7 hashMap.put(nums[i], i); 8 } 9 // 扫描nums数组,判断互补元素是否存在于Map中 10 for(int i = 0; i < nums.length; i++){ 11 int another = target - nums[i]; 12 if(hashMap.containsKey(another) && hashMap.get(another) != i){ 13 return new int[] {i, hashMap.get(another)}; 14 } 15 } 16 return null; 17 } 18 }
复杂度分析:
时间复杂度:O(n)O(n),
我们把包含有 nn 个元素的列表遍历两次。由于哈希表将查找时间缩短到 O(1)O(1) ,所以时间复杂度为 O(n)O(n)。
空间复杂度:O(n)O(n),
所需的额外空间取决于哈希表中存储的元素数量,该表中存储了 nn 个元素。
法三:一次HashMap
思路:
1. 借助一个HashMap<Integer, Integer>, 存储的元素是一个nums[i] 和 i
2. 遍历所有的元素,对于每个元素判断互补的那个元素是否在Map中,如果在根据互补的值作为键取出键值对,返回数组,退出循环
3. 如果不在,则将当前元素和下标作为键值对添加到map中
1 class Solution { 2 public int[] twoSum(int[] nums, int target) { 3 HashMap<Integer, Integer> map = new HashMap<>(); 4 for(int i = 0; i < nums.length; i++){ 5 int another = target - nums[i]; 6 if(map.containsKey(another)){ 7 int j = map.get(another); 8 return new int[] {j, i}; 9 }else{ 10 map.put(nums[i], i); 11 } 12 } 13 return null; 14 } 15 }
复杂度分析:
时间复杂度:O(n)O(n),
我们只遍历了包含有 nn 个元素的列表一次。在表中进行的每次查找只花费 O(1)O(1) 的时间。
空间复杂度:O(n)O(n),
所需的额外空间取决于哈希表中存储的元素数量,该表最多需要存储 nn 个元素。
注意:
1. HashMap的containsKey()函数的算法复杂度是O(1), 不是O(n),更不是O(n^2), 所以使用了HashMap的方式肯定比暴力的效率高,可以参考这篇博客:hashMap.containsKey(value)时间复杂度分析
2. 题解二,三都没有问题。题解二hashmap中虽然覆盖了key,但是第二次遍历时利用数组元素作为比较,而数组中元素是完好的(数组没有改动)。举例:[2,2,3,6,5],target=4,map中只有<2,1>(因为<2,0>被覆盖了),但是第二次遍历,第一个数组元素下标为0,值为2,此时下标0与hashmap中<2,1>的下标1不同,所以返回结果new int[0,1]。题解三中在map中进行put之前先进行判断,判断将要放入元素与map中元素是否满足题解条件,如果不满足再放入,当put操作覆盖map中元素的情况出现时,说明被覆盖的值和当前放入的数值相同,但是它们相加并不能满足条件(因为先判断再put),所有覆盖是没有影响的。还有因为题目说明了“假设每种输入只会对应一个答案“,所以不会出现<2, 2, 2, 3, 6, 5>这种情况
作者:LeetCode
链接:https://leetcode-cn.com/problems/two-sum/solution/liang-shu-zhi-he-by-leetcode-2/
来源:力扣(LeetCode)