题意为给出一个字符串,找出其中没有重复字符的最长子序列的长度。brute force的复杂度为O(n^3).依次查找每个子字符串是否含有重复字符,并比较长度。开始看到题目,想用DP解决,在已有目前最长子序列的情况下,比较把当前字符串放入和不放入,哪个子序列长度会更大,但是这种解法的复杂度为O(n^2),也不理想。
一种比较好的解法是贪心策略,维护一个变量maxlen保存目前已有的不重复子序列的最大长度。维护一个sliding window,left为左起点,right为右端点。同时维护一个map,保存窗口中的<char,index>键值对。每次右端点向右移动一格,如果 s[right]不在map中,则窗口中的字符串长度加1,否则说明窗口中已经有和s[right]的重复的元素,要更新left的值,left的值为重复元素的后一个值,此时也要删去重复元素之前的在窗口中的值,对map做更新,这种思路的代码如下:
class Solution(object): def lengthOfLongestSubstring(self, s): """ :type s: str :rtype: int """ length = len(s) left=maxlen = 0 map = {} for right in xrange(length): if map.has_key(s[right]): index = map[s[right]] for i in xrange(left,index+1): map.pop(s[i]) left = index+1 else: maxlen = max(maxlen,right-left+1) map[s[right]] = right return maxlen
此种解法,虽然left和right都扫了一遍,但是存在多次删map元素的过程,复杂度不能保证为O(n)。一种更优的解法,不删map元素,在取index的时候,同时判断index比不比left大,即在不在窗口中,再采取操作,代码如下:
class Solution(object): def lengthOfLongestSubstring(self, s): """ :type s: str :rtype: int """ length = len(s) maxlen = left = 0 map = {} for right in xrange(length): if map.has_key(s[right]) and map[s[right]] >= left: index = map[s[right]] left = index+1 else: maxlen = max(maxlen,right-left+1) map[s[right]] = right return maxlen
时间复杂度O(n),存储空间为常量大小,最大256,所以空间复杂度为O(1)。