3. 無重複字符的最長子串
給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。
示例 3:
輸入: “pwwkew”
輸出: 3
解釋: 因爲無重複字符的最長子串是 “wke”,所以其長度爲 3。
請注意,你的答案必須是 子串 的長度,“pwke” 是一個子序列,不是子串。
思路:如果遍歷所有子串並檢查子串中字符是否重複,時間複雜度爲O(n3),可以維護一個窗口,窗口中所有的字符都不重複,不斷擴充窗口右端,當擴充後的窗口不滿足條件,就收縮窗口左端。
採用哈希表來查找元素是否出現過,查重操作就可以在O(1)時間內完成。
時間複雜度爲O(n),n爲字符串的長度。
class Solution{
public:
int lengthOfLongestSubstring(string s){
//s[start,end) 前面包含 後面不包含
int start(0), end(0), length(0), result(0);
int sSize = int(s.size());
//hash[c] = 1表示窗口內有字符c,爲0表示窗口內沒有c
unordered_map<char, int> hash;
while (end < sSize){
char tmpChar = s[end];
//當窗口右端end可以擴展
if (hash.find(tmpChar) == hash.end() || hash[tmpChar] == 0){
hash[tmpChar] ++;
end++;
//窗口擴展,嘗試更新答案
result = max(result, end - start);
}else{
//收縮窗口左端
hash[s[start]] --;
start++;
}
}
return result;
}
};
優化:上述哈希表映射的只是字符c是否在窗口內。考慮當我們擴充窗口右部,窗口內的字符串不滿足條件必然是窗口右部剛剛新加入的字符,如果我們把hash表的值設爲字符c出現的下標,那麼當條件不滿足的時候,只需要將窗口的左部改變爲hash[c]+1
,即跳過遍歷前面所有含c
的子串(因爲窗口已經有一個字符c了)。
時間複雜度:O(n)