算法题解记录1+++百日筑基

题目及说明:

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

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

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

限制:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

思路:

        本题只有一个条件:两个数的和为target。

        那么,我们先了解一下,一个长度为n的数组(n>=2),2个数有多少种组合方式?

        n=2时,a、b,只有{{a,b}}1种。

        n=3时,a、b、c,有{{a,b},{a,c},{b,c}}3种。

        n=4时,a、b、c、d,有6种。

        我们容易发现:在数组nums1中,添加一个元素(新数组命名为nums2),nums2的组合数,就相当于在nums1的基础上,使nums2与nums1的所有元素都组合一遍。

        比如:n=2,与n=3,差别在于n=3时,c与a、b都组合了一遍。

        n=3,与n=4,差别在于d与a/b/c组合了一遍。

        【当然,观察也可得到,nums中元素的增加,与组合方式个数的增加,实际满足等差数列的关系】

        当n++时,Sn与Sn-1的差值,与Sn-1与Sn-2的差值,恒差1。

        如:当n=2,Sn=1,设a1=1;

        当n=3,Sn=3,差值为2;

        当n=4,Sn=6,差值为3;

        当n=5,Sn=10,差值为4;

        ……

        即差值是以a1=2,d=1的等差数列。【以差值2开始计算差值】

        Sn的序列为1,3,6,10,15,21……

        差值为2,3,4,5,6,7,8……

        也就是满足,Sn=Sn-1+差值n(n-1)。

        比如S2=S1+n1;S3=S2+n2。

        又因为Sn-1=Sn-2+n(n-2)。

        并且存在关系:n1=2,n2=3……n(n-1)=n,代入数字,即

        Sn - Sn-1 = n,

        Sn-1 - Sn-2 = n-1,

        Sn-2 - Sn-3 = n-2,

        ……

        S3 - S2 = 3,

        S2 - S1 = 2.

        左右全加,有:

        Sn - S1 = n + n-1 + n-2 + …… + 3 + 2

        又因为S1 = 1,故Sn = n + n-1 + …… + 1;

        所有Sn = 0.5 * n * (n-1);

解题方法1(for嵌套遍历): 

        对于这个数据量,最经典、朴素的方法是:for循环嵌套遍历

        

        拿到两个数据,相加判断是否为target(或者相减,其速度差不多)

        这道题的难点,只在于如何遍历所有数据。

解题方法2(Hash表):

       上述方法时间复杂度较高。
        现在给你一张可以定位的表table,再给你一个target,和一个值num1,请你从表table中找到另一个num2,使得num2+num1=target。

        我们不用遍历该表table,因为可以直接定位(table提供了定位方法get)

        1.如何操作?【num1一定在结果集中】

        直接table.get(target-num1),即可获得对应值。

        然而,我们不需要值,而是需要数组对应的下标。

        2.所以,该如何拿到下标呢?

        如果是链表,我们应该在数据域中定义下标、值两个数据,这样就能定位。

        问题解决了。

        不过,链表的访问速度也比较慢,因为其不能随机访问,其查找效率为O(n)。

        如果是一个排序好的数组,支持随机访问,好像效率高了。

        可是问题又来了,最开始提供的工具里,没有排序好的数组,只有一个普通数组。

        如果先排序再查找,由于在nums里不确定num1(两个数都不确定),所以还是需要遍历。

        3.就算假设已经确定num1,排序算法的效率也很低。因此,有什么不需要过多的操作,可以快速访问数据的数据结构吗?

        HashMap,由于该题只需要定位两个数字(下标、值),所以key、value的组合,恰好可以对应。

        朴素的思想是,将下标存进HashMap的key,值存入HashMap的value中。

        4.然而,HashMap的value与key并不是一一对应的关系,可能一个value对应几个key(类似函数y与x的关系),因此,Java没给我们提供根据value找key的方法。

        反过来,一个key对应一个Value,所以干脆将下标存入value,值存入key中【因为下标具有唯一性,存入value后也能避免哈希冲突】

        5.问题转换成了:我们没有天生的Hash结构,即使创建一个HashMap,里面也没有值。

        因此,我们需要向HashMap中存入数据。

        6.但是,如果先将数据存入,又有些慢了【假设存储n次,后续遍历n/2次,相加,时复为O(N),相对下面的慢一点】

        所以,我们需要一边存储,一边查找。

        7.什么意思?HashMap中没有数据,查找什么?

        想一想,我们需要的是2个数据的下标,由于题目规定答案只有一组。

        8.那么,如果哈希表中有数据1的下标,在数组nums中遇到数据2时,是不是可以不用查找其它数据?

        综上所述,答案如下:

以上内容即我想分享的关于力扣热题1的一些知识。

我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值