題目:給定乙個字串,請你找出其中不含有重複字元的 最長子串 的長度。
示例:輸入: s = "abcabcbb"
輸出: 3
解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3
思路1:遍歷字串的每個字元,如果字元在雜湊表中沒有,就新增到雜湊表中去,直到已經在雜湊表中存在的即找到重複的了,記錄最長的字元長度,清空雜湊表,然後再從第2個字元開始向後遍歷,以此類推直到遍歷到最後乙個字元結束,時間複雜度為o(n²)。
classsolution
set.add(s.charat(j));
}maxlen = math.max(maxlen, j -i);
}return
maxlen;
}}
思路2:在思路1的基礎上優化,假設從i遍歷到k時,k重複了,按照上面的方法是j要從i+1重新開始遍歷,實際上是沒有必要的,因為i+1到k-1之間是沒有重複的,只需要從k接著向後遍歷就可以了,因此j可以從k的位置繼續向後,只需要將i向後移動乙個即可,但要注意的是這種情況我們復用了之前儲存在雜湊表中的值,因此當i向後移動乙個時要將前面的從雜湊表中去除。時間複雜度為o(n)。
classsolution
for (; j < s.length(); j++)
set.add(s.charat(j));
}//可以用while替換上面的for迴圈
/*while (j < s.length())
set.add(s.charat(j));
j++;
}*/maxlen = math.max(maxlen, j -i);
}return
maxlen;
}}
思路三:在思路二的基礎上,考慮用hashmap同時儲存字元和它的下標,這樣當遇到重複字元時,可以直接將i定位到這個重複字元的後面,而不是定位到i+1,但是同樣的也要將前面的字元從雜湊表中移除,因此還需要迴圈同樣的次數去執行remove操作,但是整體的迴圈次數是減小的,省去了一些重複的判斷過程。時間複雜度同樣為o(n)。
classsolution
map.put(s.charat(j), j);
j++;
}maxlen = math.max(maxlen, j -i);
if (j ==s.length())
index =i;
i = map.get(s.charat(j)) + 1;
//將前面的字元從雜湊表中移除
for (int k = index; k < i; k++)
}return
maxlen;
}}
更進一步地,還可以直接用陣列來代替雜湊表,因為char型別的資料可以轉換成整數,從題目中給的輸入來看,乙個長度為128的int或short陣列應該可以滿足,而陣列的下標就代表char型別的資料,元素的值代表在字串中的索引,這樣可以獲得更高的效率、占用更小的空間。
總結:本題的最佳解決思路就是採用滑動視窗,思路二和三就是,把i當成左視窗邊界,j當成右視窗邊界,開始視窗長度為0,i、j都在下標為0的位置,此時j依次向右滑,當遇到重複字元的時候,就將i向右滑,只不過思路二是每次i向右滑一步,而思路三是i直接滑到重複字元的下乙個,也就是讓視窗中的內容滿足要求。**實現上,我覺得思路三更符合滑動串列埠的思路,而思路二實現起來則更簡潔。
【最佳】後來在題解中看到一種更巧妙的解法,不需要remove map中的字元。
classsolution
map.put(s.charat(right), right);
maxlen = math.max(maxlen, right - left + 1);
}return
maxlen;
}}
3 無重複字元的最長子串
給定乙個字串,找出不含有重複字元的最長子串的長度。示例 給定 abcabcbb 沒有重複字元的最長子串是 abc 那麼長度就是3。給定 bbbbb 最長的子串就是 b 長度是1。給定 pwwkew 最長子串是 wke 長度是3。請注意答案必須是乙個子串,pwke 是 子串行 而不是子串。思路 用 i...
3 無重複字元的最長子串
給定乙個字串,找出不含有重複字元的最長子串的長度。示例 1 輸入 abcabcbb 輸出 3 解釋 無重複字元的最長子串是 abc 其長度為 3。示例 2 輸入 bbbbb 輸出 1 解釋 無重複字元的最長子串是 b 其長度為 1。示例 3 輸入 pwwkew 輸出 3 解釋 無重複字元的最長子串是...
3 無重複字元的最長子串
給定乙個字串,請你找出其中不含有重複字元的最長子串的長度。示例 1 輸入 abcabcbb 輸出 3解釋 因為無重複字元的最長子串是 abc 所以其長度為 3。示例 2 輸入 bbbbb 輸出 1解釋 因為無重複字元的最長子串是 b 所以其長度為 1。示例 3 輸入 pwwkew 輸出 3解釋 因為...