LeetCode刷题心得——两数之和

LeetCode刷题心得——两数之和

  • 0.前言
  • 1.题目介绍
  • 2.题目分析
  • 3.解答
    • 3.1.方案一
    • 3.2.方案二
    • 3.2.方案三
  • 4.总结

0.前言

这道题目应该是包括我在内的第一次刷LeetCode的第一题,反正给我感觉是不简单.把自己的心得记录总结下来.因为最近刚刚学了Python,打算用Python练练手,这次选择了Python3作为编程语言.

1.题目介绍

# 给定一个整数数组 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)

2.题目分析

简单来说就是给一个数组和一个目的值,返回数组里之和等于目标值的两个数的下标,乍一看并不是很难

3.解答

3.1.方案一

最朴素的想法就是写两个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]

这是我写出的第一个答案,时间和空间都惨不忍睹
LeetCode刷题心得——两数之和_第1张图片

3.2.方案二

如何优化呢?我们想一下,如果不进行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)]

一些注意事项都在代码中用注释标识出来了,还是比较好理解的.

3.2.方案三

再想想能不能继续优化,考虑一下,在判断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的情况.这个解法我真的想不到.膜拜大神.

4.总结

第一个LeetCode题目,我花费了很长时间,仔细思考了很多才弄明白这些缘由,有点吃力,但是坚持下去就好了.一点点来吧.

你可能感兴趣的:(LeetCode刷题心得,leetcode,数据结构,算法,python)