两数之和
题目
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解析
最暴力的算法就是利用两层遍历,看两数之和是否与目标值相等,时间复杂度为o(n^2)。例如
def twoSum(self, nums: List[int], target: int) -> List[int]:
number = len(nums)
for i in range(number):
j = i+1
while(j<number):
if target == nums[i] + nums[j]:
return [i,j]
break
else:
j += 1
这里存在一个问题是在每一次对比时都需要计算一次和,那么就需要耗费巨大的时间,可能导致超时,我们可以将和转化为差,即计算与第一层遍历数加和为目标值的数,然后第二层查看该数是否在后边的列表中。
def twoSum(self, nums: List[int], target: int) -> List[int]:
number = len(nums)
for i in range(number):
temp = target - nums[i]
if temp in nums[i+1:]:
index = [i, nums.index(temp, i+1)]
break
else:
index = []
return index
还可以通过哈希表和字典的方式进行计算。哈希表是保持数组中的每个元素与其索引相互对应的最好方法。哈希表可以用空间换取查找时间,以 近似 恒定的时间进行快速查找,可以将查找时间从o(n)降低到o(1),可是一旦出现冲突,查找时间就可能会退化到o(n)。
此方法需要进行两次迭代,第一次是将列表的值与空间位置相对应,这里就需要用到enumerate() 函数,它用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。第二次迭代是进行查找。
def twoSum(self, nums: List[int], target: int) -> List[int]:
halist = {}
for idx, num in enumerate(nums):
halist[num] = idx
for i, num in enumerate(nums):
j = halist.get(target - num)
if j != None and i != j:
return [i, j]
其实这里也可以简单的理解为第一个循环是建立了一个坐标与数值对应的字典,第二个循环是依次遍历这个字典,并查找符合条件的值,只是不需要再像上边一个算法一样再来一遍循环寻找那个差值,直接从字典中查找并返回空间坐标,这样就极大的缩短了查找时间。