又咕咕了半个月,终于想起自己的密码了,这次就把初入Leetcode的一个题集sum写给大家~
1.Two Sum:
给定一个整数数组
nums
和一个目标值target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
作为Leetcode妇孺皆知的第一题,其实给的难度也不小了(至少我刚接触的时候会无法入手)。
(1)暴力算法(容易超时)
首先的解法肯定是大家一开始就会想到并且排除的暴力算法,使用两个for循环进行搜索,满足条件就返回值可行是可行,但是会超时,所以这里放个代码仅供参考。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
h_len = len(nums)
for i in range(h_len):
for j in range(i+1,h_len):
if nums[i] + nums[j] == target:
return [i,j]
(2)字典储值
使用python中的dict,和C++中的map功能一样,建立一个字典,字典的关键字是这组数的值,字典的内容是这组数的值,我们查找target-nums(size)和nums(size)是否在字典中来找到答案。
简单来说,就是将target减去每个数的值放入字典,然后如果元素里面有一个数等于这个值,便返回结果。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
d={}
size=0
while size < len(nums):
if target-nums[size] in d:
if d[target-nums[size]] < size:
return [d[target-nums[size]],size]
else:
d[nums[size]] = size
size = size + 1
(3)夹逼定理(其实就是双指针啦)
如果是有序的数组,那么我们可以用“夹逼定理”来处理。简单来说就是首尾相加,如果比target大,则将尾数左移,如果小了首尾右移,直到两个数相加刚好等于target,那么我们可以先将数组排序,然后用“夹逼定理”,这种方法的时间复杂度为O(nlogn)。
这种方法要注意的是排序的时候要记录数组原来的位置,然后再排序。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
h_nums = nums.copy()
h_nums.sort()
h_len = len(h_nums)
i = 0
j = h_len - 1
while(1):
if h_nums[i] + h_nums[j] == target:
if nums.index(h_nums[i]) == nums.index(h_nums[j]):
a = nums.index(h_nums[i])
nums.remove(h_nums[i])
j = nums.index(h_nums[i]) + 1
return [a, j]
else:
return [nums.index(h_nums[i]), nums.index(h_nums[j])]
elif h_nums[i] + h_nums[j] > target:
j = j - 1
continue
elif h_nums[i] + h_nums[j] < target:
i = i + 1
15.Three Sum:
给定一个包含 n 个整数的数组
nums
,判断nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
作为第一道题的引申,其实掌握了第一道题的双指针解法做出这题很简单。
(1)三指针
设立三个游标指针,分别放在排序后的数列的第一个、第二个还有最后一个位置。然后只要第二三个指针所指向的数字等于第一个位置的数字就可以添加到答案里。
需要注意:避免答案重复,在添加完答案后应该跳过重复数字
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
l = len(nums)
if l < 3 :return []
nums.sort()
re = []
for i in range(l - 1):
if i > 0 and nums[i] == nums[i - 1]:
continue
j = i + 1
k = l - 1
target = nums[i] * -1
while j < k:
if nums[j] + nums[k] == target:
re.append([nums[i],nums[j],nums[k]])
j += 1
while j < k and nums[j] == nums[j - 1]:
j += 1
elif nums[j] + nums[k] < target:
j += 1
elif nums[j] + nums[k] > target:
k -= 1
return re
(2)??
这种解法是我上网查的,说来惭愧,我到现在都没弄懂,评论区有会的大佬麻烦教教俺...
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if len(nums) < 3: return []
counter = collections.Counter(nums)
tri = [[0,0,0]] if counter[0] > 2 else []
neg, pos = [x for x in counter if x < 0], [x for x in counter if x >= 0]
for n in neg:
for p in pos:
x = -n-p
if x in counter:
if x in {n, p} and counter[x] > 1: tri.append([n,x,p])
if x < n: tri.append([x,n,p])
if x > p: tri.append([n,p,x])
return tri
18.Four Sum:
给定一个包含 n 个整数的数组
nums
和一个目标值target
,判断nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与target
相等?找出所有满足条件且不重复的四元组。注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
四数之和其实也可以看成三数之和的拓展,无外乎加上一层for并且要注意避免重复。
(1)四指针:
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
l = len(nums)
if l < 4:return []
re = []
nums.sort()
for i in range(l - 3):
for j in range(i + 1,l - 2):
first,last = j + 1,l - 1
while first < last:
n = nums[j] + nums[first] + nums[last]
if nums[i] + n == target:
x = [nums[i],nums[j],nums[first],nums[last]]
if x not in re:
re.append(x)
first += 1
last -= 1
elif nums[i] + n < target:
first += 1
elif nums[i] + n > target:
last -= 1
return re
(2)暴力优化
这题也是看到网上的大佬做的,优化到了一个神奇的点,别问第四个for是怎么来的,问就是崩溃了=。=
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
if len(nums)<4: return []
if target<nums[0]+nums[1]+nums[2]+nums[3]: return []
if target>nums[-1]+nums[-2]+nums[-3]+nums[-4]: return []
if target==-236727523:
return [[-79583480,-70078020,-65863359,-21202664],[-76072023,-59608044,-58094433,-42953023]]
result=[]
for i in range(0,len(nums)-3):
if target<nums[i]+nums[i+1]+nums[i+2]+nums[i+3]: continue
if target>nums[i]+nums[-1]+nums[-2]+nums[-3]: continue
for j in range(i+1,len(nums)-2):
m=len(nums)-1
for k in range(j+1,len(nums)-1):
for l in range(m,k,-1):
#print(i,j,k,l)
if nums[i]+nums[j]+nums[k]+nums[l]==target:
r=[nums[i],nums[j],nums[k],nums[l]]
r.sort()
if r not in result:
result.append(r)
m=l
break
elif nums[i]+nums[j]+nums[k]+nums[l]<target:
m=l
break
return result
以上就是Leetcode的Sum类的简单题,其中有些解法是网上大佬的思路和代码,但是由于一些原因,我没能找到题目的链接,如果有看到的朋友可以帮我贴一下链接,尊重原创,谢谢啦。