[1]两数之和
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
解题:
方法一:暴力枚举
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
if nums[i] + nums[j] == target:
return [i, j]
return []
问题一:self怎么用?
self指向对象,谁创建的对象,就指向谁
问题二:nums: List[int]
target: int) -> List[int]
这种定义方法
这是python中用于类型检查的静态类型。它允许您定义输入参数和返回的类型,以便预先处理某些不兼容性。它们只是注释,而不是实际的静态类型。
方法二:哈希表(降低时间复杂度)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashtable = dict()
for i, num in enumerate(nums):
if target - num in hashtable:
return [hashtable[target - num], i]
hashtable[num] = i
return []
问题一:dict()怎么用?
dict() 函数用于创建一个字典。
一般用法:
>>>dict() # 创建空字典
{}
>>> dict(a='a', b='b', t='t') # 传入关键字
{'a': 'a', 'b': 'b', 't': 't'}
>>> dict(zip(['one', 'two', 'three'], [1, 2, 3])) # 映射函数方式来构造字典
{'three': 3, 'two': 2, 'one': 1}
>>> dict([('one', 1), ('two', 2), ('three', 3)]) # 可迭代对象方式来构造字典
{'three': 3, 'two': 2, 'one': 1}
前面是键(key),后面是值(value),组成键值对。: ,}
访问:
d = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
print "dict['Name']: ", dict['Name']
>>>d['Name']: Zara
dict['Age'] = 8 # 更新
dict['School'] = "RUNOOB" # 添加
del dict['Name'] # 删除键是'Name'的条目
dict.clear() # 清空字典所有条目
del dict # 删除字典
注意:
- 字典值可以没有限制地取任何python对象
- 不允许同一个键出现两次🤗😎,会被覆盖成一个
- 键必须不可变,所以可以用数字,字符串或元组充当,所以用列表就不行
其他用法:
cmp(dict1, dict2) #比较两个字典元素。
len(dict)#计算字典元素个数,即键的总数。
str(dict)#输出字典可打印的字符串表示。
type(variable)#返回输入的变量类型,如果变量是字典就返回字典类型。
>>>type(dict)
<class 'dict'>
dict.clear()#删除字典内所有元素
dict.copy()#返回一个字典的浅复制
dict.fromkeys(seq[, val])#创建一个新字典,以序列 seq 中元素做字典的键,val 为字典所有键对应的初始值
dict.get(key, default=None)#返回指定键的值,如果值不在字典中返回default值
dict.items()#以列表返回可遍历的(键, 值) 元组数组
dict.keys()#以列表返回一个字典所有的键
dict.setdefault(key, default=None)#和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
dict.update(dict2)#把字典dict2的键/值对更新到dict里
dict.values()#以列表返回字典中的所有值
pop(key[,default])#删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
popitem()#返回并删除字典中的最后一对键和值。
问题二:enumerate()怎么用?
enumerate()
函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
以下是 enumerate() 方法的语法:
enumerate(sequence, [start=0])
- sequence – 一个序列、迭代器或其他支持迭代对象。
- start – 下标起始位置。
用法:
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]#所有东西
>>> list(enumerate(seasons, start=1)) # 小标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
它其实实现的是一个for循环
i = 0
seq = ['one', 'two', 'three']
for element in seq:
print(i, seq[i])
i += 1
seq = ['one', 'two', 'three']
for i, element in enumerate(seq):
print(i, element)
表达更简洁,速度有没有变快就不知道了,内存肯定是变大了
测试速度:
step = 10000
T1 = time.perf_counter()
for k in range(step):
i = 0
seq = ['one', 'two', 'three']
for element in seq:
pass
# print(i, seq[i])
i += 1
T2 = time.perf_counter()
T11 = time.perf_counter()
for j in range(step):
seq = ['one', 'two', 'three']
for i, element in enumerate(seq):
pass
# print(i, element)
T21 = time.perf_counter()
print('1程序运行时间:%s毫秒' % ((T2 - T1) * 1000))
print('2程序运行时间:%s毫秒\n' % ((T21 - T11) * 1000))
1程序运行时间:2.10769999999999毫秒
2程序运行时间:2.3905000000000176毫秒
一万次0.1ms等于没差距,但是当加上print函数就不一样了
1程序运行时间:211.4754毫秒
2程序运行时间:429.7692毫秒
相差一倍,帅哥疑惑
开始我以为跟print(i,seq[i])
和print(i,element)
中i无关
把i去掉只print(element)
和print(seq[i])
1程序运行时间:135.3671毫秒
2程序运行时间:108.89389999999999毫秒
这里就讲到为什么enumerate方法占用内存大了,enumerate方法需要给每个i分配地址,每次内部i+1结束分配新的地址,而for方法只需要分配一个地址给i,然后+1地址不变,所以enumerate方法的print多了个找地址的过程。