LeetCode-3. 无重复字符的最长子串
问题描述
- 给定一个字符串,寻找该字符串中不包含重复字符的最长子串的长度。
算法步骤
- 初始化两个指针:
left
和right
分别表示窗口的左右边界。 - 扩展右边界:向右移动
right
指针以扩展窗口,直到窗口包含重复字符。 - 收缩左边界:一旦发现重复字符,向右移动
left
指针以缩小窗口,直到窗口不再包含重复字符。 - 更新结果:在每一步中,更新不含重复字符的最长子串的长度。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
ans = 0
left = 0
cnt = defaultdict(int) # 维护从下标 left 到下标 right 的字符
for right, x in enumerate(s):
cnt[x] += 1
while left <= right and cnt[x] >= 2:
cnt[s[left]] -= 1
left += 1 # 缩小窗口
ans = max(ans, right - left + 1) # 更新窗口长度最大值
return ans
LeetCode-2024. 考试的最大困扰度
题意
- 求给定字符串
answerKey
的一个最长子串,该子串至多包含k
个T
或者至多包含k
个F
。
算法步骤
-
初始化:定义两个指针
left
和right
,分别表示子串的左右端点。定义一个计数器cnt
用于记录子串中T
和F
的数量。 -
扩展右端点:
- 遍历
answerKey
,逐渐增加right
指针。 - 将
answerKey[right]
的出现次数加一。
- 遍历
-
调整左端点:
- 如果
T
和F
的出现次数都超过k
,则不断移动左端点left
,同时减少answerKey[left]
的出现次数,直到T
和F
的出现次数至少有一个小于或等于k
。
- 如果
-
更新结果:
- 每次循环结束后,用子串长度
right - left + 1
更新答案的最大值。
- 每次循环结束后,用子串长度
-
返回答案:
- 遍历结束后,返回记录的最长有效子串长度。
class Solution:
def maxConsecutiveAnswers(self, answerKey: str, k: int) -> int:
ans = left = 0
cnt = defaultdict(int)
for right, ch in enumerate(answerKey):
cnt[ch] += 1
while left <= right and cnt['T'] > k and cnt['F'] > k:
cnt[answerKey[left]] -= 1
left += 1
ans = max(ans, right - left + 1)
return ans
LeetCode-1004. 最大连续1的个数 III
题意
- 在一个由二进制数字(0 或 1)组成的数组中,找到一个最长的连续子数组,该子数组中最多包含
k
个 0。
算法步骤
-
初始化变量:
ans
:用来存储最大长度的结果。left
:滑动窗口的左边界。cnt
:用于统计 0 的个数,类型为defaultdict(int)
。
-
遍历数组:
- 使用索引
right
遍历数组nums
,代表滑动窗口的右边界。 - 当遇到数字 0 时,在
cnt
中将 0 的数量加一。
- 使用索引
-
调整左边界:
- 当
cnt
中 0 的数量超过k
时,移动窗口的左边界left
,直至窗口中 0 的数量小于等于k
。 - 如果
nums[left]
为 0,则相应地将cnt
中 0 的数量减一。 - 左边界每移动一次,都需要更新
ans
,记录最大子数组的长度。
- 当
-
返回结果:
- 遍历结束后,返回
ans
,表示最长的满足条件的子数组长度。
- 遍历结束后,返回
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
ans = 0
left = 0
cnt = defaultdict(int)
for right, x in enumerate(nums):
if x == 0:
cnt[x] += 1
while left <= right and cnt[x] > k:
if nums[left] == 0:
cnt[nums[left]] -= 1
left += 1
ans = max(ans, right - left + 1)
return ans
LeetCode-3090. 每个字符最多出现两次的最长子字符串
题意
- 在给定字符串
s
中找到最长的子串,使得子串中任何字符的出现次数不超过 2 次。
算法步骤
-
初始化:
ans
:用来存储遍历过程中符合条件的最大子串长度。left
:滑动窗口的左边界。cnt
:字典,用来计数窗口内每个字符的出现次数。
-
遍历字符串:
- 使用变量
right
作为滑动窗口的右边界,并遍历字符串s
。 - 对于每个字符
x
,增加cnt[x]
的计数。
- 使用变量
-
调整窗口左边界:
- 当某个字符
x
的计数达到 3 时,需要调整窗口的左边界left
,以确保窗口内所有字符的最大出现次数不超过 2。 - 减少
s[left]
在cnt
中的计数,并将left
向右移动。
- 当某个字符
-
更新结果:
- 在每次右边界向右移动后,更新
ans
的值,使其为当前窗口的长度和历史最长长度中的较大值。
- 在每次右边界向右移动后,更新
-
返回结果:
- 遍历完成后,返回
ans
作为最终的结果。
- 遍历完成后,返回
class Solution:
def maximumLengthSubstring(self, s: str) -> int:
ans = 0
left = 0
cnt = defaultdict(int)
for right, x in enumerate(s):
cnt[x] += 1
while left <= right and cnt[x] >= 3:
cnt[s[left]] -= 1
left += 1
ans = max(ans, right - left + 1)
return ans