LeetCode刷题第一题,两数之和与哈希表的运用
题目描述
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
方法一:用Python中list的相关函数解决
思路:解题的关键是找到 " num2=target-num1" 是否在给定的整数数组nums(list)中。使用如下的两个方法解决:
- num2 in list, 返回值为true,说明第二个数也在数组列表list中;
- nums.index(num2),找到num2在数组列表中的索引值,也就是第二个数字的位置。
代码函数如下:
class Solution:
def twoSum(self, nums: List[int], target: int):
lens = len(nums)
j=-1
for i in range(lens):
if (target - nums[i]) in nums:
if (nums.count(target - nums[i]) == 1)&(target - nums[i] == nums[i]):#如果num2=num1,且nums中只出现了一次,说明找到是num1本身。
continue
else:
j = nums.index(target - nums[i],i+1) #index(x,i+1)是从num1后的序列后找num2
break
if j>0:
return [i,j]
else:
return []
执行通过,不过耗时较长,为1048ms。
在上述方法的基础上改进算法,想着,num2 的查找并不需要每次从 nums 查找一遍,只需要从 num1 位置之前或之后查找即可。但为了方便 index 这里选择从 num1 位置之前查找:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
lens=len(nums)
j=-1
for i in range (1,lens):
temp=nums[:i]
if (target-nums[i]) in temp:
j=nums.index(target-nums[i])
break
if j>=0:
return [i,j]
执行通过,耗时减少一半多为444ms。
算法复杂度分析
时间复杂度:对于每个元素,我们试图通过遍历数组的其余部分来寻找它所对应的目标元素,所以对应的时间复杂度是O(n)*O(n);
空间复杂度是:O(n)。
方法二:排序+双指针法
这里先将数组排序好O(nlogn),再利用双指针法遍历一遍O(n)得到结果。为了保存下标信息另开了一个数组。
时间复杂度O(nlogn),空间复杂度O(n)
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
temp=nums.copy()
temp.sort()
i=0
j=len(nums)-1
while i<j:
if (temp[i]+temp[j])>target:
j=j-1
elif (temp[i]+temp[j])<target:
i=i+1
else:
break
p=nums.index(temp[i])
nums.pop(p)
k=nums.index(temp[j])
if k>=p:
k=k+1
return [p,k]
执行通过,使用时间76ms,大幅缩短运行时间。
方法三:hash法
利用 undered_map 数组构造映射,遍历 nums[i] 时,看 target-nums[i] 是否存在hash表中即可。
时间复杂度O(n),空间复杂度O(n)
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashset={}
for i in range(len(nums)):
if hashset.get(target-nums[i]) is not None :
return [hashset.get(target-nums[i]),i]
hashset[nums[i]]=i
执行通过,运行时间76ms。