题目:76. 最小覆盖子串
难度:困难
算法:滑动窗口
class Solution:
def minWindow(self, s: str, t: str) -> str:
# 需要两个计数,一个计t中剩下字符的长度,一个计t中每个字符各自的计数
# 字典统计--方法1
lookup = collections.Counter(t)
# # 字典统计--方法2
# lookup = collections.defaultdict(int)
# for c in t:
# lookup[c] += 1
left, right = 0, 0
counter = len(t)
min_len = inf
ans = ""
while right < len(s):
if lookup[s[right]] > 0:
counter -= 1
# 比如s = [A, B], t = [B],这里遍历A的时候,把lookup[A]至为-1-----------QQQQ
lookup[s[right]] -= 1
# print("s[right] = ", s[right], "// lookup[s[right]] = ", lookup[s[right]])
right += 1
while counter == 0:
if min_len > right - left:
min_len = right - left
ans = s[left: right]
# 如果不是里面是字符,对应的lookup[s[start]]是负数,就不会让counter+=1,也就出不了这个循环,所以会不断缩小左边无用的窗口
# 所以这边判断的时候,lookup[A] != 0,就不会把counter+1跳出循环--------------QQQQ
if lookup[s[left]] == 0:
counter += 1
# 所以这边在左移窗口的时候不会有其他影响,只是把之前加进来的再移出去--------------QQQQ
lookup[s[left]] += 1
left += 1
return ans
题目:567. 字符串的排列
难度:中等
算法:滑动窗口
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
# 字典化s1子串m个字符
counter1 = collections.Counter(s1)
left = 0
right = len(s1) - 1
# 字典化ss2子串的m-1个字符
counter2 = collections.Counter(s2[0: right])
# print(counter1)
# print(counter2)
while right < len(s2):
# 往里面加一次s2[right]的字典统计,这时长度正好和s1的字典化长度一致,可以比较一次了
counter2[s2[right]] += 1
# print(counter2)
# 进行比较,如果相等,可以返回true
if counter2 == counter1:
return True
# 如果上面没相等,移出左边的s2[left]
counter2[s2[left]] -= 1
# 此时判断下是不是左边这个字典化为0,是的话要delete才行
if counter2[s2[left]] == 0:
# counter2.pop(s2[left]) --------------这么写也行
del counter2[s2[left]]
# 窗口同时右移动,保持窗口长度不变
left += 1
right += 1
return False
大佬题解:https://leetcode-cn.com/problems/permutation-in-string/solution/zhu-shi-chao-xiang-xi-de-hua-dong-chuang-rc7d/
题目:438. 找到字符串中所有字母异位词
难度:中等
算法:滑动窗口
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
# 字典化p,长度 len(p)
counter1 = collections.Counter(p)
left = 0
right = len(p) - 1
# 字典化s,长度 len(p) - 1
counter2 = collections.Counter(s[0: right])
ans = []
while right < len(s):
# 长度变成 len(p)
counter2[s[right]] += 1
# 判断下是否相等
if counter2 == counter1:
ans.append(left)
# 窗口右移
counter2[s[left]] -= 1
# delete字典中val为0的
if counter2[s[left]] == 0:
del counter2[s[left]]
# 窗口整体移动
right += 1
left += 1
return ans
题目:11. 盛最多水的容器
难度:中等
算法:双指针
class Solution:
def maxArea(self, height: List[int]) -> int:
left = 0
right = len(height) - 1
max_area = 0
while left < right:
# 计算面积并记录最大面积
tmp_area = min(height[left], height[right]) * (right - left)
max_area = max(max_area, tmp_area)
# 二选一,要用elif,移动高度低的指针
if height[left] <= height[right]:
left += 1
elif height[right] < height[left]:
right -= 1
return max_area
题目:128. 最长连续序列
难度:中等
算法:双指针
lass Solution:
def longestConsecutive(self, nums: List[int]) -> int:
# 特殊情况处理
if not nums:
return 0
if len(nums) == 1:
return 1
# 用set去重
nums = list(set(nums))
# 排序以方便用双指针
nums = sorted(nums)
# 双指针与初始长度,之前没去重的时候,遇到【0,0】tmp_len没有变化,直接统计max_len = 0就错了,所以max_len要初始化乘 = 1
left, right = 0, 1
tmp_len, max_len = 1, 1
while right < len(nums):
# 等于上一个数则长度增加
if nums[right] == nums[right - 1] + 1:
tmp_len = right - left + 1
max_len = max(max_len, tmp_len)
right += 1
# 否则left指针重新从right处计数--left不用来做nums[left]与nums[right]比较,而是用来做index定位窗口长度
else:
left = right
right += 1
return max_len
题目:15. 三数之和
难度:中等
算法:双指针
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if len(nums) < 3:
return []
ans = []
nums = sorted(nums)
for i in range(len(nums)):
# 去除i出重复情况
if i >= 1 and nums[i] == nums[i - 1]:
continue
left = i + 1
right = len(nums) - 1
while left < right:
if nums[i] + nums[left] + nums[right] == 0:
ans.append([nums[i], nums[left], nums[right]])
# 去除left处重复情况
while left < right and nums[left] == nums[left + 1]:
left += 1
# 去除right出重复情况
while left < right and nums[right] == nums[right - 1]:
right -= 1
left += 1
right -= 1
elif nums[i] + nums[left] + nums[right] < 0:
left += 1
elif nums[i] + nums[left] + nums[right] > 0:
right -= 1
# ans = list(set(ans))---不可行,报错
return ans
题目:2105. 给植物浇水 II
难度:中等
算法:双指针
# 2022.08.14
class Solution:
def minimumRefill(self, plants: List[int], capacityA: int, capacityB: int) -> int:
# 双指针
n = len(plants)
position_a, position_b = 0, n - 1
remain_a, remain_b = capacityA, capacityB
ans = 0
# 没相遇时,各自计算
while position_a < position_b:
# 情况一:如果没超过容量,直接减去
if remain_a >= plants[position_a]:
remain_a -= plants[position_a]
# 必须是elif,如果是if的话会挨个判断
# 情况二:如果超过容量,加满容量后再减去
elif remain_a < plants[position_a]:
remain_a = capacityA - plants[position_a]
ans += 1
# 左指针右移
position_a += 1
# 同情况一
if remain_b >= plants[position_b]:
remain_b -= plants[position_b]
# 同情况二
elif remain_b < plants[position_b]:
remain_b = capacityB - plants[position_b]
ans += 1
# 右指针左移
position_b -= 1
# 如果奇数相遇,单独判断一次,且只判断加水情况,不加水的不做任何处理就可以了
if position_a == position_b:
if remain_a >= remain_b and remain_a < plants[position_a]:
ans += 1
if remain_a < remain_b and remain_b < plants[position_b]:
ans += 1
return ans