题目简述
给定一个随机整型列表,返回两个数的序号,使得它们的和等于给定的目标数。题目假设返回的结果是唯一的,当没有满足的解时返回空值即可。
解法一:暴力求解
每个人最先想到都是暴力求解,对列表中的每一个数,分别和其后面的数相加判断是否等于给定的目标数。
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
n = len(nums)
for i in range(n):
a = nums[i]
for j in range(i+1, n):
b = nums[j]
if a + b == target:
return [i, j]
考虑一种较差的情况,列表中不存在满足条件的解,那么算法需要运行次。线上测试时间为6504ms,因为有很大概率需要遍历列表中的所有数字,自然结果不如人意。
解法二:前向匹配
对列表中的每一个数,和序号在它前面的数进行匹配。具体的实现中用一个字典存放遍历过的数,遍历到一个新的数,从字典中搜索是否存在一个数满足两者相加等于目标值。
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
d = {}
for j in range(len(nums):
try:
for k in d.keys():
if d[k] == target - nums[j]:
return [k, j]
d[j] = nums[j]
except Exception as e:
raise
解法二在实现上依旧存在缺陷,字典中的键值为数字在列表中的序号,这导致每次需要展开一个循环去匹配键值。线上测试时间为3152ms。对上述代码最直接的改进便是利用数字作为字典的键值,充分利用python3字典自带的__getitem__()函数。但是字典的键值通常是唯一的,相同的数字会覆盖前者。在本题中,由于采用的是向前匹配,如果存在一种输入,列表为1213,目标值为4时,这时解不是唯一的。以上情况是和题意不符的,可以不以考虑。
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
d = {}
for i in range(len(nums)):
if target - nums[i] in d:
return [d[target - nums[i]], i]
else:
d[nums[i]] = i
改进后的解法线上测试大致在30~40ms。
总结
python3的效率还是低了点,有兴趣的同学可以尝试使用c/c++或者java,应该用时会比较短。第一次写technology blog,有什么不足请多多谅解。