思路:從左往右掃字符時,每遇到一個字符,在處理時都要往回看(進行對比),這種狀況下棧的數據結構是很適合用的。以下圖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('');
}複製代碼