字符串/数组去重

1. 祖马(连续地消除邻接的相同字符:aabbbacaa --> c)

思路:从左往右扫字符时,每遇到一个字符,在处理时都要往回看(进行对比),这种情况下栈的数据结构是很适合用的。如下图


方法一:

一个指针i(向后扫描),一个栈result(存放最终结果)

case 1: 如果str[i] !== result.top,直接把这个字符放进结果栈里面

case 2: 如果str[i] === result.top,指针继续往后移动,直到遇到跟栈顶不一样的,然后把栈顶弹出,这样就相当于联同中间的一样的全部一次剔除。但是不把这个新的加进去,而是i--去启动下一个循环,因为这个新的虽然跟它的直接前驱不同,但有可能跟你很久之前放进result的字符一样。

因为js的数组没有top或者peek方法去看栈顶元素,但是大家都知道array[array.length - 1]就是最后一个元素了。下面上代码:

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。

方法二:

不用单独声明一个栈,直接用两个快慢指针模仿栈。

慢指针slow总是指向(想象的)栈顶,所以str的0~slow间的值即为result,快指针i还是做他以前的工作。

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('');
}复制代码


转载于:https://juejin.im/post/5cba69a16fb9a0688e0678ac

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值