给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。示例 2:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
自己的算法:
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
s1 = []
s_length = len(s)
ans,i,j = 0,0,0
while(i<s_length and j <s_length):
if s[j] not in s1:
s1.append(s[j])
j+=1
ans = max(ans,j-i)
else:
s1.remove(s[i])
i+=1
return ans
成功
执行用时: 172 ms, 在Longest Substring Without Repeating Characters的Python3提交中击败了29.94%的用户
内存消耗: 6.6 MB, 在Longest Substring Without Repeating Characters的Python3提交中击败了95.81%的用户
进行下一个挑战:
首先自己的算法是参考了官方解答的,因为之前就做过类似的题,但是思路一般都是暴利求解,就是嵌套循环。但是感觉很low。所以想换一种好一点的思路,下面好好说一下该思路。
在暴力法中,我们会反复检查一个子字符串是否含有有重复的字符,但这是没有必要的。如果从索引i到j-1之间的子字符串sij已经被检查为没有重复字符。我们只需要检查是s[j]对应的字符是否已经存在于子字符串sij中。
要检查一个字符是否已经在子字符串中,我们可以用O(1)的时间来完成对字符是否在当前的子字符串中检查。
滑动窗口是数组/字符串问题中常用的抽象概念。窗口通常时是在数组/字符串中由开始和结束索引定义一些列元素的集合,即[i.j)(左闭,右开)。而滑动窗口是可以将两个边界向某一方向‘滑动’的窗口。例如,我们将[i,j)向右滑动1个元素,则它将变为[i+1,j+1)(左闭,右开)。
回到我们的问题,我们使用HashSet将字符存储在当前窗口[i,j)(最初j=i)中。然后我们向右侧滑动索引j,如果它不在HashSet中,我们会继续滑动j。知道s[j]已经存在于HashSet中。此时,我们找到的没有重复字符的最长子字符串将会以索引i开头。如果我们队所有的i也这样做,就可以得到答案。
终于懂了滑动窗口!! 的概念,借助了两个变量i,j。 需要多加练习,巩固该方法的思路