Leetcode力扣 1 | 两数之和 Two Sum
该系列以提高编程能力、学习数据结构与算法为目的
- 编程语言:python
Question
给定一个数组nums、一个目标target值(以下简写成nums、target)
我们的目的是在nums中,找到两个元素,使其相加等于target值,然后返回这两个元素在nums中的索引,就是数组下标。
题目中给了三个示例:
- 第一个返回下标0和1,因为2与7的和为9
- 第二个返回下标1和2,因为2与4的和为6
- 第三个返回下标3和3,因为3与3的和为6
前面两个例子比较好理解。第三个 由于有相同的元素, 所以在编程的时候可能返回同一个索引,题目要求是同一个元素不能重复出现。所以示例3如果返回0,0则不符合要求。
这是特殊的情况,需要考虑到。
我一开始也没注意这个点。所以接下来看解答的时候如何避免返回相同元素。
Answer
Brute Force 暴力求解法
我们将第一个示例修改一下顺序进行讲解:
- 首先我们要找到两个数的和为9
- 考虑先从数组的nums[0]开始,
- 然后依次遍历nums[0]+nums[i], i = 1, 2, 3……
这里的i从1开始,也就是0的下一位开始可以避免我们前面所说的元素重复问题 - 判断语句就是if num[0] + num[i] == target
- 如果等于 我们就返回数组下标 return 0, i
- 遍历了0和剩余项的和没有找到目标元素的话
- 继续从nums[1]开始,“往后”遍历。
同样为了避免重复问题,下一层for循环的元素从nums[2]开始 - 重复上面的步骤,最后可以返回数组
最后这题返回的是[2, 3]
下面是具体代码
- 暴力求解的时间复杂度是O(n²)
- 暴力求解的空间复杂度是O(1)
暴力求解的时间复杂度是很糟糕的,很多题都可以用暴力求解,但我们一般不用,这是作为最后的选择一般。
HashTable 哈希表法
python的字典与哈希表都是应用映射结构
哈希表在不出现“冲突”,
也就是一个key对应一个value的时候搜索的时间复杂度是O(1)
我们考虑用哈希表 我也是重新学习了一下哈希表的知识才做这题的
所以如果没有知识储备的同学 要再去理解一下哈希表再看
题目给定nums和target
首先我们把数组转换成哈希表(字典)
HashTable = {} #创建一个空字典
for i in range(len(nums)):
HashTable[nums[i]] = i
然后与暴力法类似。
- 遍历数组 diff = target - nums[ j ] (diff是difference的意思,就是提醒下标不同)
- 然后我们要在哈希表中找到是否存在key值等于diff的
for j in range(len(nums)):
diff = target - nums[j]
if (diff in HashTable) and (HashTable[diff] != j):
return [j, HashTable[diff]]
- 判断句来检测是否有这样一个key
除了判断是否存在 还需要检查这个key的value值是否是元素本身
比如题目给出的示例第三个
[3, 3] 如果按照上述哈希查找的方法 我们会找到相同的元素并返回下标
很明显这是不满足要求的
- 所以我们要在判断语句那里加上另一个判断
if (diff in HashTable) and (HashTable[diff] != j):
- 哈希方法的时间复杂度最大为O(n),这个n是在创建哈希表的时候执行的
- 在哈希表中查找给定key的value的值时间复杂度是O(1)。
- 哈希方法在发生“冲突”的时候时间复杂度降到O(n)
- 这题的Hash表key值会覆盖 这个bug暂时还不会改 但是LeetCode可以通过滴