两数之和—leetcode(Java版)

87 阅读3分钟

这个算法是我用Java写的,需要别的语言版本的,推荐一个博客网站,上面有各种语言版本。 别的语言版本在这里!

1.题目

原题目在这里! 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 为目标值 target 的那 两个 整数,并返回它们的数组下标。

示例 1: 输入:nums = [2,7,11,15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 。

示例 2: 输入:nums = [3,2,4], target = 6 因为 nums[1] + nums[2] = 2+4=6 所以返回[1,2]

示例 3: 输入:nums = [3,3], target = 6 因为nums[0] + nums[1] = 3+3 = 6 所以返回[0, 1] 。

2.暴力枚举

这种问题我们最容易想到的是暴力枚举,就是使用两层for循环来解决。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result=new int[2];    //用数组result来存储满足条件的数据的下表。
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){   //这里为什么j=i+1;这样写,你思考一下就明白了。
                if(nums[i]+nums[j]==target){
                    result[0]=i;
                    result[1]=j;
                    break;  //如果满足if条件,就把下表依次存到result数组当中,然后break打破循环。
                }
            }
        }
        return result;
    }
}

在这里插入图片描述

算法分析

时间复杂度的分析

  • 外层循环(由i控制)从数组的第一个元素开始,一直到最后一个元素。
  • 内层循环(由j控制)从i的下一个元素开始,也是一直到最后一个元素。

模拟执行过程:

  • 当i为0时,内层循环将执行n-1次。注意,数组的长度是n。
  • 当i为1时,内层循环将执行n-2次。
  • 当i为n-2时,内层循环将执行1次。
  • 当i为n-1时,内层循环将不执行。注意:因为数组的下标是0开始的,所以n-1是最后一个元素。

如果我们将所有可能的 j 值的数量加起来,我们得到:

T(n)=(n1)+(n2)++1T(n) = (n-1) + (n-2) + \ldots + 1

带入等差数列求和公式得到:

T(n)=(n1)+(n2)++1=n(n1)2T(n) = (n-1) + (n-2) + \ldots + 1 = \frac{n(n-1)}{2}

所以时间复杂度为:O(n^2)。

更简单估算的方法: 我们能很容易看出外层循环的时间复杂度为O(n),内层循环的平均时间复杂度为O(n/2),所以总的时间复杂度为O(n*n/2),即O(n^2)。

空间复杂度分析

空间复杂度为O(1),因为它只使用了常量级的额外空间来存储变量i,j

3.使用哈希表

如果想查看详细的讲解,可以查看代码随想录,这里的博客写的真的非常好。 详细讲解在这里! 注意,在这个代码中的哈希表是以下面的形式存储数据的。

  • nums[i] 是键(key)。
  • i 是值(value)。
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result=new int[2];    ////用数组result来存储满足条件的数据的下表
        //判断数组是否为 空 或者 长度等于0(其实我有点疑惑数组的长度怎么能等于0 哈哈)
        if(nums==null || nums.length==0){
            return result;
        }

        //如果不是空 或者 长度等于0,就开始使用哈希表
        Map<Integer,Integer> map=new HashMap<>();   //Map是HashMap父亲,所以这里使用多态的思想
        for(int i=0;i<nums.length;i++){
            int temp=target-nums[i];   //通过计算target-nums[i]得到与之配对的补数temp
                                       //比如:9-2=7,要判断这个7是不是在哈希表里面
            if(map.containsKey(temp)){
                result[0]=map.get(temp);    //得到temp这个数据对应的下标。
                result[1]=i;
                break;
            } 
            map.put(nums[i], i);    // 如果没找到匹配对,就把访问过的元素和下标加入到map中
        }
        return result;
    }
}

在这里插入图片描述

时间复杂度分析

由于只需要遍历一次数组,且哈希表的查找操作的时间复杂度为 O(1),因此总体时间复杂度为 O(n)。

空间复杂度分析

空间复杂度方面,额外使用了一个哈希表 map,其所需空间取决于输入数组的大小,因此空间复杂度为 O(n)。