描述:給定一個字符串,請你找出其中不含有重復字符的 最長子串 的長度。
輸入: s = "abcabcbb"
輸出:3 解釋: 因為無重復字符的最長子串是"abc",所以其
長度為 3。
輸入: s = "bbbbb"輸出: 1
解釋: 因為無重復字符的最長子串是"b",所以其長度為1.
=================================================================
思路一:暴力求解,依次從左往右,遇到相同的就直接結束,然后從后面一個字符開始,
最后的出最長子串。
{(a)bcabcbb}(a)bcabcbb 開始的最長字符串為 {(abc)abcbb}(abc)abcbb;
{a(b)cabcbb}a(b)cabcbb 開始的最長字符串為 {a(bca)bcbb}a(bca)bcbb;
{ab(c)abcbb}ab(c)abcbb 開始的最長字符串為 {ab(cab)cbb}ab(cab)cbb;
{abc(a)bcbb}abc(a)bcbb 開始的最長字符串為 {abc(abc)bb}abc(abc)bb;
{abca(b)cbb}abca(b)cbb 開始的最長字符串為 {abca(bc)bb}abca(bc)bb;
{abcab(c)bb}abcab(c)bb 開始的最長字符串為 {abcab(cb)b}abcab(cb)b;
{abcabc(b)b}abcabc(b)b 開始的最長字符串為 {abcabc(b)b}abcabc(b)b;
{abcabcb(b)}abcabcb(b) 開始的最長字符串為 {abcabcb(b)}abcabcb(b)。
完整代碼如下:
public int lengthOfLongestSubstring(String s){ int max = 0; HashMap<Character,Integer> map = new HashMap<>(); for(int i = 0;i<s.length();i++){ int cur = 0; //每次都要清零整個HashMap表
map.clear(); for(int j = i;j<s.length();j++){ if(map.containsKey(s.charAt(j))){ //遇到相同的則直接跳出循環
break; } map.put(s.charAt(j),j); cur++; } max = Math.max(max,cur); } return max; }

=================================================================
思路二:利用滑動窗口:類似於一個隊列,比如例題中的 abcav,進入這個窗口為 abc
滿足題目要求,當再進入 a隊列變成了 abca,這時候不滿足要求。所以,我們
要移動這個隊列,此時的窗口值為bca即left移動到,b位置,移動到重復值a的后
一位。相當於將與當前相同的值的左邊全部移出窗口.
時間復雜度:O(n)
===========================================================================
什么是滑動窗口:
滑動窗口算法是在一個特定大小的字符串或數組上進行操作,而不在整個
字符串和數組上操作,這就降低了問題的復雜度,從而也降低了循環的嵌套深度,
滑動窗口主要應用在數組和字符串的場景。
================================================================================
滑動窗口的基本步驟:
需要注意的是:窗口的移動是按照移動的順序來進行的;窗口的大小不一定是固
定的,可以不斷縮小或變大的。
對於滑動窗口算法的基本解題思路,以字符串S示例如下:
1.采用雙指針來指定窗口的范圍,初始化left= right=0,而索引閉區間[left,right]
便是一個窗口。
2.不斷增大窗口的right指針,直到窗口的字符串滿足要求。
3.此時停止right的增加,轉而不斷增加left指針,用於縮小窗口[left,right],直到窗
口中的字符串不在滿足要求。每增加一次left,需要更新一次結果。
4. 重復第2和第3步,直到right到達字符串的盡頭。
==============================================================================
完整代碼如下:
public int lengthOfLongestSubstring(String s){ HashMap<Character,Integer> map = new HashMap<>(); int max = 0; //最長長度 int left = 0; //滑動窗口最初為零 for(int i = 0;i<s.length();i++){ if(map.containsKey(s.charAt(i))){ //如果包含,則更新left, left = Math.max(left,map.get(s.charAt(i)+1)); //之所以要不能直接取map.get(s.charAt(i))+1是因為當前值可能不包含在有效字段里面 } map.put(s.charAt(i),i);//更新left后,不管原來的 s.charAt(i) 是否在最長子段中,我們都要將 s.charAt(i) 的位置更新為當前的i, //如果包含了,則會把之前的給覆蓋掉。 max = Math.max(max,i-left+1); //更新max } return max; }
2021-05-29