力扣1. 两数之和

1. 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

 

法一:暴力法

遍历每个元素 xx,并查找是否存在一个值与 target - xtargetx 相等的目标元素。

 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)

posted @ 2020-05-12 22:48  Lucky小黄人^_^  阅读(214)  评论(0编辑  收藏  举报