最近在刷leetcode上的题,今天遇到了一个有意思的题,故在此分享一下自己的解决过程。
题目描述:给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是子串的长度,"pwke"是一个子序列,不是子串。
解法:
起初我的想法是暴力求解,获得这个字符串的所有子串,然后通过集合去重来判断每一个子串是否存在重复元素,最终我们只需求解不存在重复元素的子串的最长长度即可。
这样的想法是没问题,很快啊,我写完了代码。代码如下:
def lengthOfLongestSubstring(s):
substr = [s[i:i+x+1] for x in range(len(s)) for i in range(len(s) - x) if len(set(s[i:i+x+1])) == len(s[i:i+x+1])]
if len(substr) != 0:
return len(max(substr,key = len))
else:
return 0
接下来简单的检查了下,我还沾沾自喜,这中等难度的题就这,四行秒了。然后运行通过了三个给定的测试,当我点击提交准备下一题时,直接寄,超时了。
然后我看了下超时的这个测试用例,这字符串太长了,我在求子串用了一个嵌套循环来计算,我分析超时就是因为这个问题。
接下来我查了很多的资料,发现leetcode官方还有许多高性能题解都是使用了滑动窗口这个方法。
滑动窗口是什么?滑动窗口算法是在给定特定窗口大小的数组或字符串上执行要求的操作。该技术可以将一部分问题中的嵌套循环转变为一个单循环,因此它可以减少时间复杂度。
滑动窗口算法在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这样就降低了问题的复杂度。
具体的滑动窗口算法是怎么样的流程,以"abcabcbb"距离。我们用图来模拟以下算法步骤:
滑动窗口保证了非重复的子串,同时在实现的过程中去掉嵌套循环实现更高的效率。
以下为滑动窗口算法:
def lengthOfLongestSubstring(s):
cur = []
listc = []
for r in range(len(s)):
while s[r] in cur:
cur.pop(0)
cur.append(s[r])
print(cur)
#print(len(cur))
listc.append(len(cur))
return max(listc)
print(lengthOfLongestSubstring("abcabcbb"))
以下为滑动窗口每一步的子串。我们最终只需获得最大的长度即可。
那这样这道题就完成了,虽然性能还是比较差,但我会持续学习进行优化。接下来我还会继续分享我在leetcode上学习中见到的有意思的题。
就写到这,有问题请指正。