#1. 两数之和
方法一:暴力枚举,两层for循环
# 定义函数
def twoSum(nums,target):
for i in nums:
for j in range(nums.index(i) + 1 , len(nums)): #nums.index(i)是i元素下标
if i + nums[j] == target:
return [nums.index(i),j]
nums = [2,7,11,15]
list1 = twoSum(nums,9) # list1接受twoSum的返回值
print(list1) #[0,1]
程序测试结果:
由此可见这种方法时间复杂度太高,有待优化。
方法二:利用字典相当于哈希表的性质。
# 定义函数
def twoSum(nums,target):
d = {}
for i, n in enumerate(nums):
m = target - n
if m in d:
return [d[m], i]
else:
d[n] = i
nums = [2,3,4]
print(nums) # 打印
list1 = twoSum(nums,6) # list1接受twoSum的返回值
print(list1)
结果截图:
程序测试结果:
#15. 三数之和
方法一: 暴力枚举,三层for循环
# 定义函数
def threeSum(nums):
res = []
for i in range(0,len(nums) - 2):
for j in range(i + 1 , len(nums) - 1):
for k in range(j + 1,len(nums)):
if (nums[i] + nums[j] + nums[k] == 0) and ([nums[i],nums[j],nums[k]] not in res):
res.append([nums[i],nums[j],nums[k]])
return res
nums = [1,23,-2,10,-8,-33,90,34,90,23,45,-24,-100]
nums.sort() # 先给nums由小到大排序
print(nums) # 打印
list1 = threeSum(nums) # list1接受threeSum的返回值
print(list1)
结果截图:
程序测试结果:
这种做法虽然在少量数据的时候快速得到答案,但时间复杂度达到了O(n^3),测试结果超出时间限制,不好,待优化。
方法二:双指针+排序
# 定义函数
def threeSum(nums):
n = len(nums)
# 数组长度不符合题目要求
if (nums == []) or (n < 3):
return []
# 数组长度符合标准
res = []
for i in range(n):
if (nums[i] > 0): # 排序后的数组如果最小的值都大于0,则三数相加不可能为0,这个操作节约了大量的计算时间,减少“无用功”。
return res
if(i > 0) and (nums[i] == nums[i - 1]):
continue # 若第一个数有重复,则直接退出此次循环,让i+1
L = i + 1 # 左指针L的初始位置为i+1
R = n - 1 # 右指针R的初始位置为n-1
while(L < R): # 当左指针小于右指针时
if(nums[i] + nums[L] + nums[R] == 0): #符合题意,将满足的数据加入列表res中
res.append([nums[i],nums[L],nums[R]])
# 做循环判断看是否重复
while(L < R and nums[L] == nums[L + 1]):
L += 1
while(L < R and nums[R] == nums[R - 1]):
R -= 1
L = L + 1
R = R - 1
elif (nums[i] + nums[L] + nums[R] > 0):
R -= 1
elif (nums[i] + nums[L] + nums[R] < 0):
L += 1
return res
nums = [1,23,-2,10,-8,-33,90,34,90,23,45,-24,-100]
print(nums)
nums.sort() # 先给nums由小到大排序
print(nums) # 打印排序后的nums
list1 = threeSum(nums) # list1接受threeSum的返回值
print(list1)
结果截图:
测试结果:
从测试结果看出来,算法优化型还有待提高。
方法三:利用集合的去重性
def threeSum(nums):
nums.sort()
n = len(nums)
# 数组长度不符合题目要求
if (nums == []) or (n < 3):
return []
# 数组长度符合标准
ans = set()
for i in range(n):
if (nums[i] > 0): # 排序后的数组如果最小的值都大于0,则三数相加不可能为0,这个操作节约了大量的计算时间,减少“无用功”。
break
L = i + 1 # 左指针L的初始位置为i+1
R = n - 1 # 右指针R的初始位置为n-1
while(L < R): # 当左指针小于右指针时
temp = nums[i] + nums[L] + nums[R]
if(temp == 0): #符合题意,将满足的数据加入集合ans中
ans.add((nums[i],nums[L],nums[R]))
L = L + 1
R = R - 1
elif (temp > 0):
R -= 1
elif (temp < 0):
L += 1
rec = []
for i in ans:
rec.append(list(i))
return rec
nums = [1,23,-2,10,-8,-33,90,34,90,23,45,-24,-100]
list1 = threeSum(nums) # list1接受threeSum的返回值
print(list1)
结果截图:
注意:
1. 集合(set)追加数据函数为add()
2. 列表(list)追加数据函数为append()
#18. 四数之和
方法:固定两个数 + 排序 + 双指针+集合去重性
这种方法是在上一题的基础上,设置两个固定数(两层循环),设置两个指针进行判断。
def fourSum( nums, target):
nums.sort()
n = len(nums)
ans = set() # 这里利用集合的去重性
for i in range(n - 3):
for j in range(i + 1, n - 2): # 固定两个数
L = j + 1 # 左指针
R = n - 1 # 右指针
while (R > L):
temp = nums[i] + nums[j] + nums[L] + nums[R]
if temp == target:
ans.add((nums[i], nums[j], nums[L], nums[R]))
L += 1
R -= 1
if temp > target:
R -= 1 # 四数之和大于target,右指针左移
if temp < target:
L += 1 # 反之,左指针右移
# 去重
rec = []
for i in ans:
rec.append(list(i)) #list()转换类型,将元组转换为列表
return rec
nums = [1,0,-1,0,-2,2]
list1 = fourSum(nums,0)
print(list1)
结果截图:
程序测试结果: