這里我們可以建立一個HashMap,建立每個字符和其最后出現位置之間的映射,然后我們需要定義兩個變量res和left,其中res用來記錄最長無重復子串的長度,left指向該無重復子串左邊的起始位置的前一個,由于是前一個,所以初始化就是-1,然后我們遍歷整個字符串,對于每一個遍歷到的字符,如果該字符已經在HashMap中存在了,并且如果其映射值大于left的話,那么更新left為當前映射值。然后映射值更新為當前坐標i,這樣保證了left始終為當前邊界的前一個位置,然后計算窗口長度的時候,直接用i-left即可,用來更新結果res。
這里解釋下程序中那個if條件語句中的兩個條件m.count(s[i]) && m[s[i]] > left,因為一旦當前字符s[i]在HashMap已經存在映射,說明當前的字符已經出現過了,而若m[s[i]] > left 成立,說明之前出現過的字符在我們的窗口內,那么如果要加上當前這個重復的字符,就要移除之前的那個,所以我們讓left賦值為m[s[i]],由于left是窗口左邊界的前一個位置(這也是left初始化為-1的原因,因為窗口左邊界是從0開始遍歷的),所以相當于已經移除出滑動窗口了。舉一個最簡單的例子"aa",當i=0時,我們建立了a->0的映射,并且此時結果res更新為1,那么當i=1的時候,我們發現a在HashMap中,并且映射值0大于left的-1,所以此時left更新為0,映射對更新為a->1,那么此時i-left還為1,不用更新結果res,那么最終結果res還為1,正確,代碼如下:
class Solution { // adaad
public:int lengthOfLongestSubstring(string s) {int res = 0, left = -1, n = s.size();unordered_map<int, int> m;for (int i = 0; i < n; ++i) {if (m.count(s[i]) && m[s[i]] > left) {left = m[s[i]]; }m[s[i]] = i;res = max(res, i - left); }return res;}
};
?