字符串/數組去重

1. 祖馬(連續地消除鄰接的相同字符:aabbbacaa --> c)

思路:從左往右掃字符時,每遇到一個字符,在處理時都要往回看(進行對比),這種狀況下棧的數據結構是很適合用的。以下圖javascript


方法一:java

一個指針i(向後掃描),一個棧result(存放最終結果)數組

case 1: 若是str[i] !== result.top,直接把這個字符放進結果棧裏面數據結構

case 2: 若是str[i] === result.top,指針繼續日後移動,直到遇到跟棧頂不同的,而後把棧頂彈出,這樣就至關於聯同中間的同樣的所有一次剔除。可是不把這個新的加進去,而是i--去啓動下一個循環,由於這個新的雖然跟它的直接前驅不一樣,但有可能跟你好久以前放進result的字符同樣。spa

由於js的數組沒有top或者peek方法去看棧頂元素,可是你們都知道array[array.length - 1]就是最後一個元素了。下面上代碼:3d

function dedupRepeatedly(str) {
    const result = []; // 雖然是數組,可是是棧,嗯。。
    
    for (let i = 0; i < str.length; i++) {
        const top = result[result.length - 1]; // 看棧頂
        if (result.length > 0 && str[i] === top) {
            // 若是相同,則一直日後看
            let j = i + 1;
            for (; j < str.length; j++) {
                if (str[j] !== top) {
                    break; // 看到不一樣的才跳出
                }
            }
            
            result.pop(); // 彈出已經放入result的那個相同的
            i = j - 1; // 回退一格,讓循環繼續跟result棧頂比較
        } else {
            result.push(str[i]);
        }
    }

    return result.join('');
}複製代碼

第一個判斷那,有人說js就算result[-1]也不會越界報錯,爲啥還要畫蛇添足?我以爲是能夠可是總有點奇技淫巧感受,畢竟就算你賦值result[-1]=2了以後result.length仍是0,這個時候就不是當數組用了而是當object。
指針

方法二:code

不用單獨聲明一個棧,直接用兩個快慢指針模仿棧。cdn

慢指針slow老是指向(想象的)棧頂,因此str的0~slow間的值即爲result,快指針i仍是作他之前的工做。blog

function dedupRepeatedly(str) {
    str = str.split(''); // 首先把str變成數組,由於string是不可變的(immutable),後面str[i] = 'v'沒用
    let slow = -1;    // 這我就直接-1開始了, 從0開始要考慮的狀況比較多就算了
    for (let i = 0; i < str.length; i++) {
        const top = str[slow];
        if (str[i] === top) {
            let j = i + 1;
            for (; j < str.length; j++) {
                if (str[j] !== top) {
                    break;
                }
            }
            
            slow--; // 棧頂指針往回移一位,至關於pop了
            i = j - 1;
        } else {
            str[++slow] = str[i]; // 設置下一個棧頂元素
        }
    }

    return str.slice(0, slow + 1).join('');
}複製代碼
相關文章
相關標籤/搜索