字符串/数组去重

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('');
}复制代码
相关文章
相关标签/搜索