目录
[3. 无重复字符的最长子串](#3. 无重复字符的最长子串)
[3090. 每个字符最多出现两次的最长子字符串](#3090. 每个字符最多出现两次的最长子字符串)
[1493. 删掉一个元素以后全为 1 的最长子数组](#1493. 删掉一个元素以后全为 1 的最长子数组)
3. 无重复字符的最长子串
题目来源:3. 无重复字符的最长子串 - 力扣(LeetCode)

分析:
- 最优解法是使用滑动窗口(双指针)技术。
- 维护一个窗口[left, right],右指针不断扩展窗口,当遇到重复字符时,左指针移动到重复字符的下一个位置。
- 可以使用哈希表记录每个字符最近出现的位置,这样能在O(1)时间内判断是否有重复并快速调整窗口。
- 整个过程中持续更新最大长度值。时间复杂度为O(n),空间复杂度为O(min(m,n)),其中m是字符集大小。
my code:
python
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
res = 0
dic = defaultdict(int)
left = 0
for right,ele in enumerate(s):
dic[ele] += 1
while dic[ele] > 1:
dic[s[left]] -= 1
left += 1
res = max(res, right - left + 1)
return res
注意:
- 非定长滑动窗口中,窗口的移动需要条件约束,当满足这个条件才能移动
- 同时要及时更新结果
- 非定长window中,移除的操作通常需要使用while,这样才能涵盖诸多情况的子序列组合
3090. 每个字符最多出现两次的最长子字符串
题目来源:3090. 每个字符最多出现两次的最长子字符串 - 力扣(LeetCode)

分析:该题与无重复字符最长子串逻辑相同,只需要把1改为2即可
解:
python
class Solution:
def maximumLengthSubstring(self, s: str) -> int:
res = 0
left = 0
dic = defaultdict(int)
for right,c in enumerate(s):
dic[c] += 1
while dic[c] > 2:
dic[s[left]] -= 1
left += 1
res = max(res,right + 1 - left)
return res
1493. 删掉一个元素以后全为 1 的最长子数组
题目来源:1493. 删掉一个元素以后全为 1 的最长子数组 - 力扣(LeetCode)

分析:
- 因为要求删掉一个元素后的子数组最大长度,所以窗口内允许存在至多一个0(非1元素)
- 可以使用字典来存储0元素个数
- 如果0元素个数大于 1 ,那么滑动窗口直至窗口内0元素数量等于1
- 子数组长度应该 right - left 而不再 +1 因为删掉了其中一个元素0
我的答案:
python
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
res = left = 0
dic = defaultdict(int)
for right,element in enumerate(nums):
if element != 1:
dic[element] += 1
while dic[element] > 1:
dic[nums[left]] -= 1
left += 1
res = max(res,right - left)
return res
标准题解:
python
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
ans = cnt0 = left = 0
for right, x in enumerate(nums):
# 1. 入,nums[right] 进入窗口
cnt0 += 1 - x # 维护窗口中的 0 的个数
while cnt0 > 1: # 不符合题目要求
# 2. 出,nums[left] 离开窗口
cnt0 -= 1 - nums[left] # 维护窗口中的 0 的个数
left += 1
# 3. 更新答案,注意不是 right-left+1,因为我们要删掉一个数
ans = max(ans, right - left)
return ans
1208. 尽可能使字符串相等
题目链接:1208. 尽可能使字符串相等 - 力扣(LeetCode)

分析:
- 内置函数可以将字符转换为对应的ascall
- abs内置函数是去绝对值
- 总开销是否大于maxCost作为移动窗口的条件
解答:
python
class Solution:
def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
res = left = 0
ans = 0 # 记录开销
for right,(s_c,t_c) in enumerate(zip(s,t)):
# 当前位需要的开销
ans_tmp = abs(ord(s_c) - ord(t_c))
# 目前总开销
ans += ans_tmp
while ans > maxCost:
# 开始移除做边
ans -= abs(ord(s[left]) - ord(t[left]))
left += 1
res = max(res,right + 1 - left)
return res