两数之和
- 最初做法:两个for循环进行一个一个的试错,直到遇到符合条件的,返回。这个程序的时间复杂度是 .
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
returnList = []
for i in range(len(nums)):
for j in range(len(nums)):
if i != j:
if(nums[i] + nums[j] == target):
returnList.append(i)
returnList.append(j)
return returnList
- 提示:解题关键主要是想找到
num2 = target - num1
是否也在nums
中,然后再返回其对应的索引。所以,第二个数字通过num2 = target - num1
找到,而不再是使用第二个for循环。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(0, len(nums)):
another = target - nums[i]
if another in nums:
if i != nums.index(another):
return [i, nums.index(another)]
print('没有结果')
- 提示:上面的做法是每次都从
nums
中找出第二个数,但实际上我们可以缩小查找范围,只需要从num1
后的位置进行查找~因为位于其前面的数,如果有符合的,早就已经返回了。
for i in range(0, len(nums)):
another = target - nums[i]
if another in nums[i+1:]:
return [i, nums[i+1:].index(another)+(i+1)]
print('没有结果')
- 执行时间并没有加快很多…毕竟时间复杂度是同一个等级的,所以还是要想其他方法…
- 提示:通过字典来模拟哈希查询的过程。
enumerate()函数
:用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据下标和数据; 返回 enumerate(枚举) 对象。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap={}
for index, num in enumerate(nums): # 将索引以及对应的值存储在一个字典中
hashmap[num] = index
for i, n in enumerate(nums):
j = hashmap.get(target - n)
if j is not None and i!=j:
return [i,j]
- 提示:上面程序先将所有值以及对应的索引保存在
hashmao
中,然后再次循环enumerate(nums)
,从hashmap
字典中查找指定的值;但实际上,我们仍然不需要在整个hashmap
字典中进行查找。下面是改进的程序,我认为它是“从后往前”查找出指定的数的。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap = {}
for index, num in enumerate(nums):
num2 = target - num
if num2 in hashmap:
return [index, hashmap[num2]]
hashmap[num] = index # num是键,index是值
三数之和
参考:https://leetcode-cn.com/problems/3sum/solution/3sumpai-xu-shuang-zhi-zhen-yi-dong-by-jyd/
- 暴力法解决的时间复杂度为 ,具体算法略。
- 除了以上的方法,我并没有想出其他解法。于是看了其他人的笔记——使用 “双指针” ,这里进行记录。
假设nums
数组如下:
Step1、将给定的nums
数组进行排序(升序)
Step2、固定三个指针中的一个指针k
到索引最小处,然后另外两个指针l
,r
分别固定在除了k
指向的位置之外的最左侧与最右侧。
Step3、双指针l
,r
交替向中间移动,记录对于每个固定指针k
的所有满足nums[k] + nums[l] + nums[r] == 0
的l
,r
组合。然而,并不是简单地直接进行算法的书写就可以了,因为我们要分析出详尽的步骤以及特殊情况:
程序如下(Python实现):
def threeSum(nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort() # 原地升序排序
result, k = [], 0 # k,l,r三个“指针”用索引来表示
for k in range(len(nums) - 2):
if nums[k] > 0:
break
if k > 0 and nums[k] == nums[k-1]:
continue
l, r = k+1, len(nums) - 1
while l < r:
s = nums[k] + nums[l] + nums[r]
if s < 0:
l += 1
while l < r and nums[l] == nums[l-1]:
l += 1
elif s > 0:
r -= 1
while l < r and nums[r] == nums[r+1]:
r -= 1
else:
result.append([nums[k], nums[l], nums[r]])
# 因为已经得到了使和为0的三个值了,所以如果再只改变l或r都不可能再得到和为0的结果;
# 而正确的做法就是使r,l同时改变,同时仍进行while判断
l += 1
r -= 1
while l < r and nums[l] == nums[l-1]:
l += 1
while l < r and nums[r] == nums[r+1]:
r -= 1
return result
print(threeSum([-1, 0, 1, 2, -1, -4]))