题目
请从字符串中找到一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
假设该字符串只包含’a’~'z’的字符。
例:
在字符串’arabcacfr’中,最长的不包含重复字符的子字符串是"acfr",长度为4。
思路
- 遍历字符串,计算以每个字符为结尾的不含重复字符的子字符串的长度,更新最长长度。这里运用了动态规划解决公共子问题。不需要向前判断到头,只需要判断到上一个重复出现的地方即可,也就是以前一个位置为结尾的最长无重复子串是否加上本位置还是无重复的。还有一个关键在于,如何能最快的判断是否存在重复字符。如果每次都向前逐个比较,总复杂度是O(n^2)。为了能在O(1)内判断,我们用建立一个缓存列表,保存此前a~z字母最后出现的位置。如果出现重复,则从前一个出现的位置开始计算新的长度,否则+1即可。
- 时间复杂度:O(n),O(n)遍历,O(1)判断重复
- 空间复杂度:O(1),固定大小的辅助数组
代码
思路1: 时间复杂度:O(n),空间复杂度:O(1)
def longest_sub_str_without_dup(string):
"""
:param string: string
:return: max length of substr with out duplication
"""
cur_len = 0 # the length of non-dup-substring ending with current position
max_len = 0 # max length of non-dup-substring ending
last_pos = [-1] * 26 # -1 = didn't appear
for i in range(len(string)):
curchr_pos_i = ord(string[i]) - ord('a') # a= 0 ~ z=25
cur_chr_pre_i = last_pos[curchr_pos_i] # last appear position
if i - cur_len > cur_chr_pre_i:
cur_len += 1
else:
cur_len = i - cur_chr_pre_i
max_len = max(max_len, cur_len) # refresh the max length
last_pos[curchr_pos_i] = i
return max_len
思考
同样的题目
LeetCode 3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 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
"""
from collections import OrderedDict
l = len(s)
sub = ''
submax = 0
for i in range(l):
if s[i] in sub:
sub = sub[sub.index(s[i]) + 1:] + s[i]
else:
sub += s[i]
submax = max(submax, len(sub))
return submax
注意:
上面这段代码,是用的O(n)的查重方式,该题目中字符串中不仅包含’a’ - 'z’还有其他的字符。为了应用思路1的代码,只需要将辅助数组的大小扩展成全ASCII的大小即可。