秒懂算法系列 —— 两数之和

您的点赞和关注是我坚持写作的最大动力,本人正在寻找测试开发的工作机会,欢迎邮件联系(log.v@qq.com)

概要

描述

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

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:

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

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

图形介绍

分析

我们拥有的资源是一个数组和一个数字,这个数字代表两个数字的和,这两个数字从给定的数组中寻找,比如题目给定的是 9 ,我们就可以从数组中找到 2 和 7 ,这就是题目需要的一组结果,我们要做的就是从数组中找出这种数字组合,并获得组合中两个数字的下标

暴力法

暴力法肯定是脑海里第一个迸出的灵感,先以第一个数字为基准,看看后面的数字能否和它凑成结果,如果可以,则返回,如果不行则继续寻找,以第一个数字为基准完成遍历后就使用下一个数字,直到找到题目所需的数字组合,很容易得到以下代码

class Solution {
    public int[] twoSum(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) { // 遍历第一个加数后面的每一个数字
                if (nums[j] == target - nums[i]) { // 判断第一个加数与第二个加数的和是否为目标值
                    return new int[] { i, j }; // 找到则返回该数字组合中两个数字的下标
                }
            }
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

如何优化?

首先我们要思考如下问题:

为什么暴力法遍历效果差?

因为我们要寻找两个数字,所以按照暴力法,对于每一个数组中的元素,我们都试图去寻找与之相加满足条件的数字,所以会额外增加一次 O ( n ) O(n) O(n) 的时间复杂度,该算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。由于没有额外的数据结构使用,该算法的空间复杂度为 O ( 1 ) O(1) O(1)

如何提升搜索效率?

可以看到,提升该算法效率的关键就是提升搜索的效率,这里我们用到了 HashMap 作为优化工具,它可以带来高效的搜索接口,该接口的 时间复杂度可以达到 O ( 1 ) O(1) O(1), 接下来我们就可以使用如下方案获取最终结果:

原理图

这就是两遍哈希表法,具体代码如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>(); // 创建 Hash 表数据结构
        for (int i = 0; i < nums.length; i++) { // 第一遍,构建哈希表
            map.put(nums[i], i);
        }
        for (int i = 0; i < nums.length; i++) { // 第二遍
            int complement = target - nums[i]; // 判断第二个加数是否在 HashMap 中,如果在则查找成功
            if (map.containsKey(complement) && map.get(complement) != i) {
                return new int[] { i, map.get(complement) };
            }
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

其中 map.containsKey(complement) 即为 O ( 1 ) O(1) O(1) 的查找方法,也是效率提升的关键,复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
    我们把包含有 n 个元素的列表遍历两次。由于哈希表将查找时间缩短到 O ( 1 ) O(1) O(1) ,所以时间复杂度为 O ( n ) O(n) O(n)

  • 空间复杂度: O ( n ) O(n) O(n)
    所需的额外空间取决于哈希表中存储的元素数量,该表中存储了 n 个元素。

第一性原理

该问题其实是一个查找 类型的问题,而两次哈希表法,实质上是一种通过缓存来优化时间效率的手段,通过在 HashMap 这个缓存中查找第二个元素,大大提升了算法效率。

参考

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值