这道题目应该是包括我在内的第一次刷LeetCode的第一题,反正给我感觉是不简单.把自己的心得记录总结下来.因为最近刚刚学了Python,打算用Python练练手,这次选择了Python3作为编程语言.
# 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
#
# 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
#
#
#
# 示例:
#
# 给定 nums = [2, 7, 11, 15], target = 9
#
# 因为 nums[0] + nums[1] = 2 + 7 = 9
# 所以返回 [0, 1]
#
# Related Topics 数组 哈希表
# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# leetcode submit region end(Prohibit modification and deletion)
简单来说就是给一个数组和一个目的值,返回数组里之和等于目标值的两个数的下标,乍一看并不是很难
最朴素的想法就是写两个for 循环遍历这个数组,把然后依次相加看是否等于目标值,如果等于直接返回数据下标.
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
for j in range(1, len(nums)):
if i == j:
break
if target == nums[i] + nums[j]:
return [i, j]
如何优化呢?我们想一下,如果不进行j循环,直接判断target-num 是否存在于nums数组中,如果存在则返回num和target-num的下标,这样应该能省一部分时间,但是如何获取到target-num的下标呢?毕竟数组可没法通过数值获取到下标的,虽然可以通过再次遍历nums和target-num比较来获取到下标,但这样的话,我们又进行了一个nums的遍历,没达到减少一次循环的目的.我们可以这样,事先把nums的下标和数值存到一个字典dict_nums中,其中下标index为value,数值num为key,这样我们就可以通过dict_nums.get(target - num)方法获取到下标了.思路大致如上,代码如下
def twoSum(self, nums: List[int], target: int) -> List[int]:
dict_nums = {}
#enumerate()为枚举函数,可以把序列进行遍历,第一个参数index为值的下标,第二个参数num为值.
#第一个for循环为构建一个字典存放下标和数值.
for index, num, in enumerate(nums):
dict_nums[num] = index
for index, num in enumerate(nums):
#为了解决target=2*num的情况,比如nums=[3,4,3],target=6
#此时如果不进行下标判断,会返回两个相同的下标(0,0),所以需要判断一下下标
if target - num in nums and index != dict_nums.get(target - num):
return [index, dict_nums.get(target - num)]
一些注意事项都在代码中用注释标识出来了,还是比较好理解的.
再想想能不能继续优化,考虑一下,在判断target-num是否在nums里的时候,我们是从整个nums里进行了判断,但事实上,并不是每次都需要这样做,因为nums中有两个数值满足target-num在nums中的条件,当我们遍历到第一个满足条件的数值的时候,另一个满足条件的数值在num的后面,而num前面的所有数值都存放在了dict_nums中,试想,我们能不能每次都num的前面或者后面遍历,这样就省去了遍历后面或者前面的步骤,因而可以节省时间.如何选择从num前面还是后面遍历呢?其实从平均时间上来说我个人感觉差别不大,但从num的前面开始遍历实现起来更方便,因为num前面的数值都存放在了dict_nums中的key中,因此选择从num前面遍历.
def twoSum(self, nums: List[int], target: int) -> List[int]:
dict_nums = {}
for index, num, in enumerate(nums):
# 判断的是target-num是否是dict_nums中的key(最开始我也觉得判断的应该是value)
#但事实就是判断key
if target - num in dict_nums:
return [index, dict_nums.get(target - num)]
# 为了防止出现target-num=num的情况,把这句话放在最后
# 比如nums=[1,3,3,2] target=6,此时判断到第一个3的时候,dict_nums中没有符合条件的数值
# 如果放在前面,因为3已经加入到dict_nums中,所以就会出现返回[1,1]的情况
dict_nums[num] = index
这个解法真的十分巧妙,一个把dict_nums[num] = index
放到最后真的巧妙,通过对已经加入到dict_nums中的数值判断,有效避免了每次都遍历一整个nums的情况.这个解法我真的想不到.膜拜大神.
第一个LeetCode题目,我花费了很长时间,仔细思考了很多才弄明白这些缘由,有点吃力,但是坚持下去就好了.一点点来吧.