LeetCode打卡练习第一题——两数之和
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
————————————————————————————————————————
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
版本python3
分析
求解两数之和,很明显我们用两个for循环遍历,很容易求解,我们就不去讲这种方法了。况且时间复杂度要小于O(n2),所以两次遍历肯定是不可以滴,我刚好前天看的哈希表,所以我的第一想法就是想能不能放到哈希表当中去尝试。而且哈希表的时间复杂度为O(1),那么我们就把复杂度降低到了O(n)。
所以总结一些就是,我们要先进行一次遍历,把各个值放到哈希表中,然后在哈希表中求值
知识储备
- 哈希表的话在python实际上就是字典,所以我们不需要额外定义类
- enumerate()函数的使用:
"""enumerate()函数可以接收一个迭代器或是可迭代对象 最后会返回以迭代器的__next__的方法返回值和一个计数值(以元组的形式) 在这里简单的理解,用法range()一样 不过在这里室友for循环时,需要用两个变量接收,分别返回的是索引和对应值""" example = ['a','b','c'] for i,k in enumerate(example): print(i,k) > 0 a > 1 b > 2 c for i in enumerate(example): print(i) > (0, 'a') > (1, 'b') > (2, 'c')
注意
值得一提的是,我们在哈希表的创建时,不能等赋值完全部的,再去哈希表中查找。因为我们需要把数放在键的位置,把索引放在值的位置,而数组中的数是可以重复的,而字典因为是无序表,所以键是不可以重复,所以我们只能一边向表里添加元素,一边判断。
还有就是,不采用哈希表的同学,只用纯粹的逻辑判断,也要注意一下多种情况,比如,存在相同数字,负数,以及相加等于0的情况等。
代码
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash = {}
for index,value in enumerate(nums):
if hash.get(target - value) is not None: #get是根据值查找键
return [index,hash.get(target - value)]
hash[value] = index
代码非常的简介,也比较好理解。
先创建一个哈希表
然后遍历数组,因为我们是通过值判断返回索引,所以使用enumerate(),当然range()也是可以的
下边的分支是指,先判断数组中这个索引的目标值是不是已经存在表中了,如果是的话就直接返回结果
不是的话,就在表中添加
这样的操作,就很好的规避了,如果不同位置相同数字在添加字典中覆盖的情况。而且,也可以注意到我们通过target-value的形式把寻找两个值变成了寻找一个值,这其实也是一个很好的点。最后再张贴一张运行效果
再看一下其它方法的运行结果做一个对比
这两种方式也是我之前测试的,很明显哈希表的效率要高的很多,而且理解起来也较为简单。
再BB一句
可能有同学也会问,为什么不能把数组的索引放在键上,把数字放在值上
- 首先我个人感觉第一个,应该是可以实现,毕竟我们演示了字典中有get()方法。但是从逻辑上讲,不论是哪一种数据结构,都应该是对值进行操作,而不是对索引或是键去进行操作。
- 虽然以那种方式可以把所有的数据存储的字典中,而且不用担心键相同的问题,但是另外一个问题就是我们只是把一坨数据从一种容器放到另外一种容器中,最后寻找的话还是要重新遍历,时间复杂度还是O(n2)
- 如果不采用遍历以上面这种形式去取值,那么不就是自行增加难度了吗,当然如果为了在女生装杯完全可以,而且及其妙哉,因为她可能一直弄不出来