1. 程式人生 > 其它 >3. 無重複字元的最長子串(LeetCode)

3. 無重複字元的最長子串(LeetCode)

題目描述


給定一個字串 s ,請你找出其中不含有重複字元的最長子串的長度。

示例1:

輸入: s = "abcabcbb"

輸出: 3

解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。

條件分析


  1. 字元無重複;
  2. 子串有連續的字元構成

解題思路(滑動視窗)


  1. 將字串拆分為字元陣列,定義一個變數maxLen儲存最長子串的長度;
  2. 定義兩個下標left,right,如果沒有重複,取maxLen為當前長度與maxLen的最大值,如果發現right和已有字元重複,則left=重複字元下標+1,right++,直到right到達末尾;
  3. 如何判斷字元在陣列中已經出現?可以考慮用一個數組freq將每個字元出現的下標記錄下來,值-1代表未出現,否則儲存的是元素的下標。注意在重置left的時候,老的left和新的left之間的freq元素也進行更新為-1,表示不再存在

編碼如下

 public int lengthOfLongestSubstring(String s) {
    char[] cs = s.toCharArray();
    int left = 0; // [left,right]為最大不重複子串
    int right = -1;
    int maxLen = 0;
    
    int[] freq = new int[256]; // 儲存元素的下標,初始情況下所有元素都不存在
    for (int i=0; i<freq.length; i++) {
        freq[i] = -1;
    }
    while (right < cs.length-1) {
        right++;
        // 元素不存在,計算最大值
        if (freq[cs[right]] == -1) {
            maxLen = max(maxLen, (right - left + 1));
        } else {
            // 元素存在,取出存在元素的下標+1,也就是left要移動到的新位置
            int newLeft = freq[cs[right]] + 1;
            // 把老的left和新的left之間的元素都設定為不存在,相當於重置
            while (left < newLeft) {
                freq[cs[left++]] = -1;
            }
            left = newLeft;
        }
        freq[cs[right]] = right;
    }
    return maxLen;
}

private int max(int max, int newMax) {
    if (newMax > max) {
        max = newMax;
    }
    return max;
}