leetcode 3:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
示例1
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例3
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
代码:
暴力解法:
# 暴力解法
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
m = 0
if s != "":
m = 1
for i in range(len(s)):
for j in range(i + 1, len(s)):
if s[i] != s[j]:
if self.check_str(s[i:j + 1]):
m = max(m, len(s[i:j + 1]))
return m
# 检查子字符串是否有重复
def check_str(self, s: str) -> bool:
for i in range(len(s)):
if s[i] in s[i+1:]:
return False
return True
if __name__ == '__main__':
s = 'abcabcbb'
sol = Solution()
print(sol.lengthOfLongestSubstring(s))
滑动窗口解法:
# 滑动窗口解法
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
# 窗口的定义
dic = {}
# 定义窗口左边和最大无重复子字符串长度为0
i ,res = 0, 0
# 向右从0依次滑动窗口右边j
for j in range(len(s)):
# 当窗口中的字符串有重复
if s[j] in dic:
#将窗口左边i向后移动
i = max(dic[s[j]], i)
# i +=1
# 获取新的最大无重复子字符串长度
res = max(res, j-i+1)
# 将j滑过的字符存入dic
dic[s[j]] = j+1
return res
if __name__ == '__main__':
s = 'abcabcbb'
sol = Solution()
print(sol.lengthOfLongestSubstring(s))
执行结果:
leetcode 30:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/
给定一个字符串s和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例1
输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。输出的顺序不重要, [9,0] 也是有效答案。
示例2
输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]
代码:
# 滑动窗口
class Solution(object):
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
if not s or len(s)==0 or not words or len(words)==0:
return []
# 将每个单词以及出现的频率记录到字典中
words_map,res = dict(),[]
for i in words:
if i not in words_map:
words_map[i] = 1
else:
words_map[i] += 1
one_word_size = len(words[0])
all_words_size = len(words)*one_word_size
for i in range(len(s)-all_words_size+1):
# 每次取 all_words_size长度的子串
tmp_str,d = s[i:i+all_words_size],dict(words_map)
# 将子串和临时字典进行比较
for j in range(0,len(tmp_str),one_word_size):
# 从子串tmp_str中取出one_word_size长度的子串,看是否出现在临时字典中
# 如果是就将临时字典记录的频率-1,如果不在就跳出循环
key = tmp_str[j:j+one_word_size]
if key in d:
d[key] -= 1
if d[key] == 0:
del d[key]
else:
break
# 当内层循环遍历完后,如果临时字典为空则表示全部匹配上了
# 记录数组的下标
if not d:
res.append(i)
return res
if __name__ == '__main__':
s = "barfoothefoobarman"
words = ["foo", "bar"]
sol = Solution()
print(sol.findSubstring(s, words))
执行结果:
leetcode 1234:https://leetcode-cn.com/problems/replace-the-substring-for-balanced-string/
有一个只含有'Q'
, 'W'
, 'E'
,'R'
四种字符,且长度为 n
的字符串。假如在该字符串中,这四个字符都恰好出现n/4
次,那么它就是一个「平衡字符串」。
给你一个这样的字符串 s
,请通过「替换一个子串」的方式,使原字符串s
变成一个「平衡字符串」。你可以用和「待替换子串」长度相同的任何其他字符串来完成替换。
请返回待替换子串的最小可能长度。
如果原字符串自身就是一个平衡字符串,则返回 0。
示例1:
输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。
示例2:
输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。
示例3:
输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。
示例4:
输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。
代码:
class Solution(object):
def balancedString(self, s):
"""
:type s: str
:rtype: int
"""
n = len(s)
average = n // 4
import collections
counter = collections.Counter(s)
saveCounter = collections.Counter()
# 所有超过1/4的都是需要转换的
for key, val in counter.items():
if val > average:
saveCounter[key] = val
if not saveCounter:
return 0
l = r = 0
count = float("inf")
for r in range(n):
# 每一个如果都要需要转化的过程中,则滑动窗口需要包含,直到滑动窗口足够大,saveCounter包含的元素对应的次数都要小于等于average
if s[r] in saveCounter:
saveCounter[s[r]] -= 1
while l <= r:
include = True
for ch in 'QWER':
if saveCounter[ch] > average:
include = False
break
if include:
# 如果滑动窗口已经包含了 那么接下来我们将左边右移,需要将s[l] 次数++
count = min(count, r - l + 1)
saveCounter[s[l]] += 1
l += 1
else:
break
return count
if __name__ == '__main__':
s = "QQQQ"
sol = Solution()
count = sol.balancedString(s)
print(count)