力扣:两数之和 难度:简单

本文介绍了LeetCode上的经典问题‘两数之和’,通过分析题意,提出并实现了一个暴力破解的O(n^2)解决方案,然后优化为O(n)的解法,利用HashMap存储数组元素及其下标,有效降低了时间复杂度。讨论了算法的空间和时间效率,强调了数据结构在解决问题中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、本题地址和题目

2、分析一下题目

3、我的解法和代码

4、优化算法和解析

5、总结和收获


1、本题地址和题目

本题是我在力扣上面做的,难度是简单级别,地址如下:

1. 两数之和 - 力扣(LeetCode) (leetcode-cn.com)

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案

下面是示例和数据范围:

2、分析一下题目

题意是很容易理解的,就是要求从给定的一个整型数组中找出两个数,这两个数的和是给定的某一个数,然后以数组的形式返回这两个数的下标。这两个数的下标不能一样 ,但是这两个数可以是相等的。题目保证有唯一的答案。根据数据的范围,最大是 十的九次方,最小是十的负九次方,而JAVA整型的范围最小是负21亿多,最大是21亿多,使用基本的int类型就可以。

3、我的解法和代码

这个题是简单类型的,可以直接暴力破解,但是复杂度会非常的高,是O(n^2)。由于力扣不像牛客ACM有时间限制,我为了尽快解题,使用了暴力破解;

暴力破解就是枚举所有可能,直到找到答案:使用双重循环。外循环是从数组的第一位直到最后一位,内循环是从外循环那一位的后一位开始,直到最后一位。如果两数字的和等于给出的数字,那么就将两个下标存入结果数组中,然后跳出外循环,返回结果数组。

我的JAVA代码如下所示:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int result[]=new int[2];
        int i,j;
 a:       for(i=0;i<nums.length;i++){
            for(j=i+1;j<nums.length;j++){
                if(nums[i]+nums[j]==target){
                    result[0]=i;
                    result[1]=j;
                    break a;
                }
            }
        }
        return result;
    }
}

可以顺利通过,但是复杂度是O(n^2),消耗内存和运行时间多。执行时间只超过26%的人,消耗内存只超过38%的人,不推荐。

4、优化算法和解析

上面的暴力破解法时间复杂度太高了,使用下面的解法降低时间复杂度:

题目就是需要我们从数组中找到两个数,这两个数的和为一个已知的数,并且答案还是唯一的。这就表明这两个数之间是有关系的。我们可以使用Map数据结构,对数组进行一次遍历。将数组中的数字作为Map的键(Key),将下标作为值(Value),这样做是因为我们最终要的就是两个下标,所以下标作为值是合理的我们每遍历一个数组中的数字的时候,就要判断Map中是否存在跟它的和是题目所给数字的那个数,也就是是否存在与之对应的那个Key,如果存在,那么我们就找到答案了,不需要将正在遍历的这个数字存到Map中,可以返回答案。如果不存在(说明Map中没有它的另一半),那么我们就将遍历到的这个数字和它的下标存入Map中。最坏的情况就是,答案中的两个坐标,一个是0,另外一个是length-1,并且各不一样,遍历到最后,Map的长度就是(length-2)-0+1。这里我多说一下,我们不需要担心数组中有相同的数字,比方说吧target是10,数组中有两个4,那么这两个4的下标也不是正确答案,我们肯定会将放在前面的一个4先放入Map中,当我们遍历到第二个4的时候,还是需要将它放入Map中的,这时候两个4都要作为Key,就产生冲突了。但是在Map的存储机制下,如果两次要存入的Key一样,Map就只会对Value做出改变,或者你可以理解为,后面的覆盖掉了前面的。由于答案是唯一的,像上面我举的例子,存在两个4,并且target是10,那么数组中一定是没有6的,否则答案就不唯一了。

上面解法的时间复杂度是O(n),因为只遍历了一次,但是存储空间消耗稍多一点,因为使用了Map记录。空间复杂度也是O(n)

下面是我的JAVA代码:

public int[] twoSum(int[] nums, int target) {
        int result[]=new int[2];
        Map<Integer,Integer> map=new HashMap<>(nums.length);
        map.put(nums[0],0);
        for (int i=1;i<nums.length;i++){
            if (map.containsKey(target-nums[i])){
                result[0]=i;
                result[1]=map.get(target-nums[i]);
                break;
            }else {
                map.put(nums[i],i);
            }
        }
        return result;
    }

最后的情况是:

运行用时超过了前100%的用户,内存消耗超过了前63%的用户。

5、总结和收获

其实这一道题利用的就是Map的特性,键值是一一对应的。况且答案是唯一的,我们用空间换时间,利用了两个数之间的关系,即  两数之和已经确定了;

这道题要注意的是键和值得确定,键和值分别是什么。

学习的一些数据结构或者是特性,不能只停留在概念上,需要能够灵活使用。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你是我的日月星河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值