第一题 无重复字符的最长子串:
给定一个字符串s,请你找出其中不含有重复字符的最长字串长度。
示例:
输入:s = "abcabcbb"
输出:3
解释:因为无重复字符的最长子串是"abc",所以长度为3
问题分析:
本题可以采用滑动窗口的思想,利用优先队列来充当滑动窗口。窗口初始化大小为0,在遇到窗口中不存在的字符,则窗口大小加一,并将该字符加入窗口(队列);若是该字符窗口中已经存在,则从队列头开始将字符依次弹出,直到窗口中没有该字符,最后将该字符加入窗口。遍历整个字符串。
代码实现:
class Solution(object): def lengthOfLongestSubstring(self, s): """ :type s: str :rtype: int """ # 滑动窗口算法 windows = [] length = 0 for i in range(len(s)): while s[i] in windows: windows.pop(0) windows.append(s[i]) if len(windows) > length: length += 1 return length
第二题 找到字符串中所有字母异位词:
给定两个字符串s和p,找到s中所有p的异位词的子串,返回这些字串的起始索引。不考虑答案输出的顺序。
示例:
输入:s = "cbaebabacd", p = "abc"
输出:[0, 6]
解释:起始索引为0的子串是"cba", 它是“abc“的异位词
起始索引为6的子串是"bac",它也是“abc”的异位词
问题分析:
首先考虑暴力解法,将p进行排序,再根据p的大小创建匹配窗口,从s的第1位一直匹配到s的第s_len - p_len + 1位,将每次窗口中的子串取出并进行排序后与排序后的p进行比较即可。
代码实现:
class Solution(object): def findAnagrams(self, s, p): """ :type s: str :type p: str :rtype: List[int] """ p_sorted = sorted(p) length = len(p) index = [] i = 0 while i < len(s): string = sorted(s[i:i+length]) if string == p_sorted: index.append(i) i += 1 return index
优化分析:
暴力解法虽然能够求出最后答案,但是时间复杂度为O(n^2*logn),运行效率太慢。为此,我们对其进行进一步的优化。在暴力算法中,由于我们每次都应用了快排来找出异位词,快排的时间复杂度为O(n*logn),带来了大量的时间消耗。在优化算法中,我们采用记录每个字母的个数来比较异位词,这样就避免了使用开排算法。时间复杂度为O(n)。
代码实现:
class Solution(object): def findAnagrams(self, s, p): """ :type s: str :type p: str :rtype: List[int] """ # 计算字符串s和p的长度 s_len, p_len = len(s), len(p) # 若s的长度小于p,则直接返回空 if s_len < p_len: return [] ans = [] # 定义数字来维护当前窗口中各个字母的数字 s_count = [0] * 26 p_count = [0] * 26 for i in range(p_len): s_count[ord(s[i]) - 97] += 1 p_count[ord(p[i]) - 97] += 1 if s_count == p_count: ans.append(0) for i in range(s_len - p_len): s_count[ord(s[i]) - 97] -= 1 s_count[ord(s[i + p_len]) - 97] += 1 if s_count == p_count: ans.append(i + 1) return ans