LeetCode刷题笔记--1.两数之和

引言:今天开始为找工作做准备,所以开始刷LeetCode上的题。本着输出的学习方式要强于输入的学习方式的思想,我打算用写博客的方式来记录我写每一道题的思路和想法。题目的序号就按LeetCode官网上的序号为准,因为刚开始我只会挑简单的做(留下了学渣的泪水),所以以后题号都会是跳着写的,读者要注意。另外,因为正在学习Python3,所以代码我都是用Python3写的。下面就开始吧。

1,.两数之和
难度:简单
题目描述:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

大致意思都可以看懂,唯一需要琢磨的可能是这句话:不能重复利用这个数组中同样的元素。 它的意思是不能用相同下标的元素计算得到target,这句话是很重要的判定条件。比如给一个数组nums=[1, 2, 3],target=4,你只能返回[1, 2],不能返回[1, 1]。
这道题官方给了3种解法。

  • 方法一:暴力法O(n^2)(没错是我了)

两层循环,第一层遍历整个nums,第二层从第一层遍历到的位置开始往后遍历。直白地说就是按顺序挨个找,以示例中的nums来说就是依次找:(2,7)、(2,11)、(2,15)、(7,11)、(7,15)…当然这里target是9,找到(2, 7)就结束了。

def twoSum(self, nums, target):
        #O(n*n)
        for index1,num1 in enumerate(nums):
	        for index2,num2 in enumerate(nums[:(-len(nums)+index1)]):
		        if(num1 + num2 == target):
			        return[index1,index2]
  • 方法二:遍历两遍哈希表O(2*n)

两个循环(注意是两个不是两层)。这里定义了一个dict类型的变量,类似于Java的hashmap类型。首先第一个遍历将nums的value作为key,将nums的index作为value赋值到hashmap中。类似:{2:0, 7:1, 11:1, 15:2},就是将nums的下标和索引倒过来存储。为什么不能用其他的数据类型而要用dict(hashmap)呢?答案在第二个遍历里。接下来是重点,这道题的实质是什么?题目描述的是让我们寻找在nums数组中是否存在两个数num1和num2, 使得num1 + num2 = target。如果就照着题目描述正面来想,要解决问题就比较困难。但如果反面来想,我们已知tartget,遍历时我们也知道当前的num,那我们不就可以用target - num得到另一个数应该是几了吗?然后再寻找数组里有没有这个值不就行了?然后就是为什么要使用dict类型存储的理由了,因为在第一遍遍历中我们将nums的索引和值倒过来存储,所以用dict可以直接用if num2 in nums来查找num2这个key是否在dict里(java的map可以用containsKey()方法)。如果确实包含,就可以返回当前的nums索引值index和hashmap的value(hashmap的value即为nums数组的索引)。当然还要判断不能返回相同的元素下标。

def twoSum(self, nums, target):
	#O(2*n)
    hashmap = {}
     for index, num in enumerate(nums):
         hashmap[num] = index
     for index, num in enumerate(nums):
         num2 = target - num    
         if (num2) in nums:
             if(index != hashmap[num2]):#判断下标不能相同
                 return [index, hashmap[num2]]
  • 方法三:一遍哈希表(这个很巧妙)
    之所以说巧妙,是因为这个方法只使用于这道题。思想和方法二是一样的,都是利用哈希表的方便特性。只是方法二是先用一个遍历将哈希表赋值,第二个遍历再查找,而方法三则是在一个遍历里就将查找和赋值都做完了。从代码中可以看出在这个方法里,dic刚开始是空的,然后对空的dict进行if num2 in hashmap,再对hashmap赋值。那如果先赋值再判断呢?就会出现这种情况:比如nums=[3,3],target=6,显然我们应该返回[0,1]。但如果先赋值的话,第一遍遍历index=0, num2=3, hashmap={3:0}, 这时hashmap里只有{3:0}, 那么hashmap[3]得到的就是0,那么return的就是[0, 0]。那么为了防止返回相同下标,我们加上if(index != hashmap[num2])判断试一下:第一遍遍历index=0, num2=3, hashmap={3:0};因为hashmap[3]=0, 所以index=hashmap[3]=0,导致第一遍没有结果,进行第二遍遍历,index=1,num2=3, hashmap={3:1},这次变成了index=hashmap[3]=1了,还是过不了if语句。结果只能返回空。原因显而易见:dict不允许存在两个重复的key,如果依次传入key相同value不同的键-值对,那么第二遍传入的键-值对就会把第一遍传入的覆盖掉。因此要想一个循环搞定这个问题,哈希表的赋值就必须在查找的后头。我们最后来推一遍正确的过程:第一遍index=0, num2=3, hashmap={}, 第一遍无返回,然后hashmap赋值,hashmap={3:0};第二遍index=1, num2=3, hashmap={3:0}, hashmap[3]=0, index = 1, return [1, 0],结果正确。
def twoSum(self, nums, target):
 	#O(n)
    hashmap = {}
    for index, num in enumerate(nums):
        num2 = target-num
        if num2 in hashmap:
            return [index, hashmap[num2]]
        hashmap[num] = index
    return None

'''
#错误答案
def twoSum(self, nums, target):
 	#O(n)
    hashmap = {}
    for index, num in enumerate(nums):
        num2 = target-num
        hashmap[num] = index
        if num2 in hashmap:
        	if(index != hashmap[num2]):#有没有这句都不对
            	return [index, hashmap[num2]]
    return None
'''
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值