Longest Substring Without Repeating Characters

。題目假設

給定一個字串,找出最長的不重複子字串

。直覺

一開始想不太出來,以為要用 dp,後來看到了提示: hashmap, two pointer 就恍然大悟,

我們可以邊掃過字元,邊丟進 hashmap裡面檢查是不是重複,一遇到重複就把 pointer 換到新的位置

。分析可行性(資結、演算法、虛擬碼)

資結:hashmap

演算法:用兩個指針,一前一後,前面邊掃邊丟進map裡面,遇到有重複的,將後指針換到該重複位置

。最後解決方案

演算法:用兩個指針,一前一後,前面邊掃邊丟進map裡面,遇到有重複的,將後指針換到該重複位置的後一個,

然後要把換到的位置前面都從 map 裡刪掉

。反饋:與一開始想的不一樣的地方、需改進的想法

與直覺幾分相似,不一樣得點是一開始我沒有用兩個指針,而是一個指針往前掃而已,

一個指針遇到 dvdf 這個例子就不行了 ,因為會將指針定位到第二個 d ,v 就沒有算進去,要用兩個指針,

遇到重複時將後指針定位到重複的後一個。

我的寫法是這樣:

while (p1 <= length && p2 <= length) {
    if (!map.containsKey(s.charAt(p1))) {
        map.put(s.charAt(p1), p1); 
    } else {
        max = Math.max(max, map.size());
        int tempP2 = map.get(s.charAt(p1)) + 1;
        for(int i=p2; i<tempP2; i++)
            map.remove(s.charAt(i));
        p2 = tempP2;
        map.put(s.charAt(p1), p1);
    }
    p1++;
}

後來看到更好的方法:

HashMap<Character, Integer> map = new HashMap<>(); //char, index
int max = 0;
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);
    }
    map.put(s.charAt(i), i);
    max = Math.max(max, i-j+1);
}
return max;

其中的

j = Math.max(j, map.get(s.charAt(i)) + 1);

意思就是說每當遇到重複時,我要定位到重複位置的後一個,但又不能在目前的位置之前

看一下這個例子 abba,遇到第二個 b ,我們會把 j 定位到 2,遇到第二個 a 時,我們不能把 j 往回定位到 1

(不能往回到 index = 1 也是上面 hash map 要刪掉之前元素的理由)

反饋的點是:兩根指針的使用流程、index定位在當前和之後的寫法

。複雜度

掃一遍,O(log n)

results matching ""

    No results matching ""