LeetCode Longest Substring Without Repeating Characters(003)解法總結

NewCoder1024發表於2020-03-10

描述

Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", with the length of 3. 複製程式碼

Example 2:

Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.複製程式碼

Example 3:

Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3. 
             Note that the answer must be a substring, 
             "pwke" is a subsequence and not a substring.複製程式碼

思路

首先想到使用暴力解法,即使用每個字母作為開始,分別計算當前字母的最長不重複子串。從這些最長串長度中選擇最長的串。

對於最長不重複子串的記錄使用HashSet,使用size()函式確定當前串的長度。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int maxLen = 0;
        for(int i = 0;i<s.length();i++){
            int thisLen = 0;
            Set<Character> temp = new HashSet<Character>();
            for(int j = i;j<s.length();j++){
                if(temp.contains(s.charAt(j))){
                    break;
                }else if(s.charAt(i) != s.charAt(j)){
                    temp.add(s.charAt(j));
                }else if(j == i){
                    temp.add(s.charAt(j));
                }else{
                    break;
                }
            }
            thisLen = temp.size();
            maxLen = (thisLen>maxLen?thisLen:maxLen);
        }
        return maxLen;
    }
}複製程式碼

可以暴力AC,但是時間複雜度和空間複雜度都不是很好。

Runtime: 125 ms, faster than 8.48% of Java online submissions for Longest Substring Without Repeating Characters.
Memory Usage: 42.2 MB, less than 5.20% of Java online submissions for Longest Substring Without Repeating Characters.

優化

看到問題討論區有使用map作為字串出現記錄工具的,這個程式碼很巧妙的解決了去重的問題,並且只用遍歷一遍陣列。經典的KMP演算法也是避免反覆對字串進行比對,兩者有異曲同工之妙。

the basic idea is, keep a hashmap which stores the characters in string as keys and their positions as values, and keep two pointers which define the max substring. move the right pointer to scan through the string , and meanwhile update the hashmap. If the character is already in the hashmap, then move the left pointer to the right of the same character last found. Note that the two pointers can only move forward.

public int lengthOfLongestSubstring(String s) {
    if (s.length()==0) return 0;
    HashMap<Character, Integer> map = new HashMap<Character, Integer>();
    int max=0;

    //使用i,j下標指示器,j作為收尾指標,i作為開頭指標
    //j = Math.max(j,map.get(s.charAt(i))+1)巧妙的保證i,j所含的區域沒有重合的字元
    for (int i=0, j=0; i<s.length(); i++){
        if (map.containsKey(s.charAt(i))){
            j = Math.max(j,map.get(s.charAt(i))+1);
        }
        //將打頭的i指向的字元做記錄
        map.put(s.charAt(i),i);
        max = Math.max(max,i-j+1);
    }

    return max;
}複製程式碼
Runtime: 5 ms, faster than 88.21% of Java online submissions for Longest Substring Without Repeating Characters.
Memory Usage: 41.5 MB, less than 5.20% of Java online submissions for Longest Substring Without Repeating Characters.

可以看到時間複雜度大幅提高。

在進行字串比對時要注意看看有沒有可能不讓指標回退,可以大幅提高效率。

相關文章