📅  最后修改于: 2023-12-03 14:55:45.434000             🧑  作者: Mango
给定一个二进制字符串,其中可能包含一些 '?' 字符,将 '?' 替换为 '0' 或 '1' 后,检查子字符串 "10" 是否在所有可能的替换后出现。
输入: s = "1?0" 输出: true 解释: 替换出来的可能为 "100" 或 "110",均包含substring "10"
输入: s = "0" 输出: false
暴力解法:生成所有可能的替换并判断是否包含 "10" 子串。但这样时间复杂度太高。
考虑线性扫描字符串 s,当前位置为 i,同时记当前已遇到 ? 的个数为 count。
当 s[i] 为 ? 时,可能替换为 0 或者 1,所以 count 加 1,并将 ? 的位置 i 保存到一个数组中。
当 s[i] 不为 ? 时,需要分析前面 count 个 ?,并同时判断 i 和 i-1 位置上的字符是否能够组成 "10" 子串。如果满足条件,则将数组中最靠前的 ? 替换为 '1',否则用 '0' 替换。处理完后,将 count 重置为 0。
重要的事情说三遍:?????,当遇到的字符 s[i] 为 '?' 时,要把当前位置 i 保存到一个数组中。
def checkSubStr(s: str) -> bool:
cnt = 0 # 记录未替换的 ? 的个数
lst = [] # 记录 ? 的位置
n = len(s)
# 遍历 s
for i in range(n):
if s[i] == '?':
cnt += 1
lst.append(i)
else:
if i>0 and s[i-1] == '1' and s[i] == '0': # 判断是否存在 "10" 子串
if cnt == 0: # 如果没有 ?,直接返回 False
return False
else:
cnt -= 1
s = s[:lst[0]]+'1'+s[lst[0]+1:] # 将 ? 替换为 1,并从 lst 中删掉这个位置
lst = lst[1:] # 注意:list 的删除操作很耗时,所以要尽量使用 slice。
else:
cnt = 0 # 注意:这里千万不能忘了将 cnt 重置为 0。
return s.find('10') != -1 # 最后,判断是否存在 "10" 子串
最坏情况下遍历整个字符串,时间复杂度 $O(n)$。