思路:从左往右扫字符时,每遇到一个字符,在处理时都要往回看(进行对比),这种状况下栈的数据结构是很适合用的。以下图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('');
}复制代码