小白的LeetCode刷题日记1--python3

LeetCode第一题:两数之和

题目描述:

来自LeetCode

要求:

来自LeetCode

第一种解法 暴力穷举:

首先最容易想到的就是暴力穷举,只要能解出题就是一个方法,因为我们需要在给定的数组当中寻找两数相加的目标值,因此可以直接适用两层的for循环来对数组进行搜索:

#第一层for循环
for i in range(len(nums)):

第一层for循环用来固定要搜索的两数中的第一个数,搜索长度即数组长度,range()的范围是左开右闭的

#第二层for循环
for j in range(len(nums)):

第二层循环用来移动需要搜索的两数中的第二个数,但是题目中给定了数组的同一个元素不能同时出现,并且由于已经有了第一层循环,第二层循环如果还是由0开始,那么当i=1,2,3,…之后,j依旧从0 开始,这会导致进行不必要的重复运算,所以起始应该由i+1开始,因此第二层 for循环代码如下:

#优化后的第二层for循环
for j in range(i+1,len(nuns)):

接下来就开始判断题目条件两数相加是否等于目标值,用if判断语句来进行,如果是就直接返回下标值

if nums[i]+nums[j] == target :
	return [i,j]

最后再补一个找不到时返回空即可,完整代码如下:

def twoSum(nums, target):
    for i in range(len(nums)):
        for j in range(i+1,len(nums)):
            if nums[i]+nums[j]==target:
                return [i,j]
    return []
复杂度分析

时间复杂度:暴力穷举方法的时间复杂度主要体现在两层for循环上,当数组长度无限大时,for里面的if语句是可以省略的,因此时间复杂度为O(n^2)
空间复杂度:在代码中我们只开辟了result列表的空间,而且result的接收结果就是两个数,不管nums数组再多,result始终长度<=2(因为题目说每种输入只对应一个答案),所以空间复杂度为O(1)

优缺

LeetCode运行截图
从运行的图中可以明显看出其优缺点
优点:占用空间小
缺点:搜索费时

第二种解法 哈希表法:

第二种解法是进阶解法,暴力穷举的时间复杂度O(n^2)实际上是很慢的,因此能否进行优化来缩短搜索时间,这时利用哈希表就能大大缩短搜索时间,那么什么是哈希表?

哈希表(HashTable),也称散列表,它是利用键值对来访问的数据结构,这种索引方式的搜索时间复杂度达O(1),它在存储时首先会计算哈希码(散列值)来确定存储位置,这个计算过程是通过一个函数进行位置映射的,存储过程中数据的存放是无序的,并且唯一,但是当数据非常非常非常多时,还是可能产生存储冲突(碰撞)的,存储冲突有其相应的应对方法,比如链地址法、再散列法、开放地址法、开辟一个公共溢出区等,就不详细展开

那么在本题中,应该如何建立一个哈希表呢?

这就体现了python的便捷了,python中就有一个底层是用哈希表的方法建立的数据结构–字典(dict),既然底层涉及了哈希表,那么字典在存储时也会用到键-值对来存储数据的,数据的访问是通过键(key)计算出值(value)的位置,下面是字典的使用例子:

d = dict{}
d = {"name": "xiaobai", "age": 18}

这里的name就是键(key),xiaobai就是值(value)

除了用到字典,我们还需要利用到一个函数–enumerate(),enumerate的中文释义便是列举、枚举的意思,它的作用是将一个可迭代对象(iterable)组成一个索引序列,这个索引序列包含下标和值的对应情况,【可迭代对象指像列表、元组、集合、字典、字符串等】,例子如下:

list = ["name","xiaobai","age","18"]
for i in enumerate(list):
    print(i)

输出
已经知道所需要的武器,那么就开始使用了,首先我们定义一个接收列表result和一个字典hashTable,因为我们需要存储的是下标和值的关系,这时候就能利用enumerate函数来对nums数组进行划分,用key和value变量来接收对应的,因为到时候利用字典查找的时候是两数中的另一个数,因此在存储的时候将数组值存在键(key)中,将下标存在值(value)中,这样可以减少一定的搜索时间,代码如下:

hashTable = {}
for value,key in enumerate(nums):

ps:顺便说下,只需要一次循环即可,因为在查表和建表是在一个for里面进行的,而且两数是先后出现的,因此只需一次for循环,无需建完表后再进行查找

这时候再设置一个if判断语句用于查找,我们是在字典中查找目前能够和当前搜索数字相加为目标值的数字,因此利用target - key来对字典进行查找,如果查找得到,就返回字典里面数对应的下标,如果查不到,就将当前的key和value存入hashTable中

if target - key in hashTable:
	return [hashTable[target - key],value]
hashTable[key] = value

最后再补一个找不到时返回空即可,完整代码如下:

def twoSum(nums, target):	
	hashTable = {}
	for value,key in enumerate(nums):
		if target - key in hashTable:
			return [hashTable[target - key],value]
		hashTable[key] = value
	return []
复杂度分析

时间复杂度:哈希表法的时间开销主要是在哈希表的建立上,在最坏情况下的时候是需要遍历整个数组的,因此时间复杂度为O(N),但是搜索时是直接查找哈希表的,因此搜索的时间为O(1)
空间复杂度:需要开辟一个哈希表的空间,这个空间最多的时候是整个数组都存进去,因此空间复杂度为O(N)

优缺

在这里插入图片描述
优点:速度快,相比于暴力穷举快了不止一个档次
缺点:空间耗费大(但是也不太算缺点,因为在有条件的情况下,往往会选择以空间换时间,毕竟人的时间是有限的,不能随意浪费,还需珍惜时间)

最后,运行时间的长短还和电脑性能有关,本人电脑并不算好(doge)

以上参考:力扣官方题解

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值