一、18. 四数之和
相向双指针,参考灵神代码(. - 力扣(LeetCode)),特别是优化部分很神。代码如下:
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
n = len(nums)
ans = []
nums.sort()
if n < 4:
return ans
for a in range(n-3):
if a > 0 and nums[a] == nums[a-1]: # 去重
continue
if nums[a]+nums[a+1]+nums[a+2]+nums[a+3] > target: # 优化
return ans
if nums[a]+nums[-1]+nums[-2]+nums[-3] < target:
continue
for b in range(a+1,n-2):
if b>a+1 and nums[b] == nums[b-1]:
continue
if nums[a]+nums[b]+nums[b+1]+nums[b+2] > target: #优化
break
if nums[a]+nums[b]+nums[-1]+nums[-2] < target:
continue
c,d = b+1,n-1
while c<d:
if c>b+1 and nums[c] == nums[c-1]: # 去重
c += 1
continue
if d < n-1 and nums[d] == nums[d+1]:
d -= 1
continue
cur = nums[a]+nums[b]+nums[c]+nums[d]
if cur == target:
ans.append([nums[a],nums[b],nums[c],nums[d]])
c+=1 # 注意这里两个指针均需改变
d-=1
elif cur > target:
d -= 1
else:
c += 1
return ans
相向双指针:
当时我没有想到遍历大的数,就使用的同向双指针,后面看了灵神题解(. - 力扣(LeetCode))才反应过来,枚举最大边,就变成了a+b > target的题目了,就能使用相向双指针来达到目的。另外增加了两个优化,代码如下:
class Solution:
def triangleNumber(self, nums: List[int]) -> int:
# 相向双指针
nums.sort()
n = len(nums)
ans = 0
for c in range(n-1,1,-1):
if nums[c-2]+nums[c-1] <= nums[c]: #优化
continue
if nums[0]+nums[1] > nums[c]:
ans += c*(c-1)//2
continue
a,b = 0,c-1
while a<b:
if nums[a]+nums[b] > nums[c]:
ans += b-a
b -= 1
else:
a += 1
return ans
三、42. 接雨水
1.分层遍历(但是超时了)
思路:将它一层一层地看,记录单层接水量然后相加。虽然我已经做了优化了,但是时复毕竟是O(n^2),又1 <= n <= 2 * 10^4
,所以还是超时了。代码如下:
class Solution:
def trap(self, height: List[int]) -> int:
# 超时
maxhigh = max(height)
ans = 0
flag = 0 #记录是不是每一层第一次出现的
a,b = 0,len(height)-1 # 优化,记录每一次最左最右范围
for i in range(1,maxhigh+1):
for j in range(a,b+1):
if height[j] >= i:
if flag == 0:
flag = 1
a = j
else:
ans += j-1-foreidx
foreidx = j #上一个出现的坐标
b = j
flag = 0
return ans
2.前后缀分解
学习视频:盛最多水的容器 接雨水_哔哩哔哩_bilibili
class Solution:
def trap(self, height: List[int]) -> int:
# 前后缀分解
# 时复O(n),空复O(n)
n = len(height)
pre_max = [0]*n
pre_max[0] = height[0]
for i in range(1,n):
pre_max[i] = max(pre_max[i-1],height[i])
suf_max = [0]*n
suf_max[-1] = height[-1] # 逆序遍历,逆序输入
for i in range(n-2,-1,-1):
suf_max[i] = max(suf_max[i+1],height[i])
ans = 0
for h, pre, suf in zip(height,pre_max,suf_max):
ans += min(pre,suf) - h
return ans
2024.3.16续:
3.相向双指针
方法来自学习视频。太妙了!!!!(土拨鼠尖叫!!!!)
class Solution:
def trap(self, height: List[int]) -> int:
# 相向双指针 时复O(n),空复O(1)
n = len(height)
ans = 0
l,r = 0,n-1
pre_max = 0
suf_max = 0
while l<r:
pre_max = max(pre_max, height[l])
suf_max = max(suf_max, height[r])
if pre_max < suf_max:
ans += pre_max - height[l]
l += 1
else:
ans += suf_max - height[r]
r -= 1
return ans
感谢你看到这里!一起加油吧!