LeetCode 3: Longest Substring Without Repeating Characters
Description:
Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
描述:
给定一个字符串,返回该字符串最长无重复子串,即最长的不包含重复字符的子字符串。
示例:
给定字符串 “abcabcbb”, 答案为 “abc”,长度为3; 给定字符串 “bbbb”, 答案为 “b”, 长度为1; 给定字符串 “pwwkew”, 答案为 “wke”,长度为3. 注意,答案必须为子串,“pwke”是子序列,但不是子字符串。
方法一:暴力破解
遍历字符串的每个子串,并判断相应子串中是否存在重复字符。
class Solution { public: int lengthOfLongestSubstring(string s) { if(s.length() == 0) { return 0; } int maxLen = 0; for(int i = 0; i < s.length(); i++) { for(int j = i + 1; j < s.length() + 1; j++) { if(hasRepeatChar(s, i, j)) { break; } int len = j - i; if(len > maxLen) { maxLen = len; } } } return maxLen; } bool hasRepeatChar(string s, int start, int end) { set<int> c; for(int i = start; i < end; i++) { if(c.count(s[i]) != 0) { return true; } c.insert(s[i]); } return false; } };
该方法的时间复杂度为O(n3),空间复杂度为O(n)。
然而,该方法时间复杂度较高,导致Time Limit Exceeded.
方法二:滑动窗口
class Solution { public: int lengthOfLongestSubstring(string s) { int len = s.length(); int i = 0, j = 0; int maxLen = 0; set<int> charSet; while(i < len && j < len) { if(charSet.count(s[j]) == 0) { charSet.insert(s[j++]); int max = j - i; maxLen = max > maxLen ? max : maxLen; } else { charSet.erase(s[i++]); } } return maxLen; } };
本方法时间复杂度为O(n),空间复杂度为O(min(m,n)),其中n为字符串长度,m为字母表中字符个数。
方法三:滑动窗口优化方法。
上述方法中,对于存在重复字符的子串区间[i,j),将i值右移,开始处理子区间[i+1, j)。
可以采用map结构存储子串区间中每个字符和其位置的对应关系,对于子区间[i,j),如果字符S[j]存在于[i,j)中,且S[j]在区间的位置为k,则直接从区间[k + 1,j)开始判断。
例如,子串[i,j)的值为"pass", 其字符S[j]的值为‘a’,子直接开始由子串"ss"开始判断,而不是由子串"ass"开始。
class Solution { public: int lengthOfLongestSubstring(string s) { int len = s.length(); int i = 0, j = 0; int maxLen = 0; map<int, int> m; while(j < len) { if(m.find(s[j]) != m.end()) { i = m[s[j]] >= i ? m[s[j]] + 1 : i; } int max = j - i + 1; maxLen = max > maxLen ? max : maxLen; m[s[j]] = j; j++; } return maxLen; } };