前端必备数据结构:(栈)用正则奇妙解决的算法问题:解压缩字符串

题目描述:
小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,对于字符串中连续的m个相同字符串S将会压缩为m|S,例如字符串ABCABCABC将会被压缩为[3|ABC],现在小Q的同学收到了小Q发送过来的字符串,你能帮助他进行解压缩么?

输入例子1:
"HG[3|B[2|CA]]F"

输出例子1:
"HGBCACABCACABCACAF"

例子说明1:
HG[3|B[2|CA]]F>HG[3|BCACA]F>HGBCACABCACABCACAF

这是之前参加腾讯的笔试,遇到的一题,其中我第一次想到的是递归和栈,但是太复杂了。很多细节要考虑,直到看到这个解法,yyds

function compress( str ) {
var a = /\[(\d+)\|([a-zA-Z]+)\]/g
    while(str.indexOf("[") >= 0){
        str = str.replace(a,(b,$1,$2) =>{
        	// $1,$2 分别代表的是正则分组匹配结果。
        	// 2  CA
        	// 3 BCACA
        	
            var result = "";
            for(let i = 0; i<$1; i++){
                result += $2;
            }
            return result;
            })
    }
    console.log(str)
}
var str = "HG[3|B[2|CA]]F"
compress(str)

讲解下自己的思路:
写了一个复杂的代码,也是由于替换思想点拨了思路。
先找到左半边的括号 [ ,放进栈里,直到遇到 右半边括号 ], 就弹出栈顶,存入栈是存的左括号的下标,因为思路是替换左半括号和右半括号之间的内容,所以需要开始和结束的下标,直到字符串遍历结束。


代码稍微有点复杂,我会注释讲解

function compress( str ) {
            return unzip(str)
        }
        // 此方法就是替换[ ]之间的内容,包括括号,是在整个字符串上进行替换
        var getStr = function (begin, end, arr) {
            let num = ''; // 保存压缩次数
            let cur = ''; // 保存压缩字符串
            let result = ''; //保存解压后的值
			
			// 因为begin是 [ 的下标,所以我从下一位开始,当然就从begin开始也可以的
            for (let i = begin + 1; i < end; i++) {
                if (arr[i] >= '0' && arr[i] <= '9') {
                    num = num + arr[i]; // 拿到压缩次数
                } else if (arr[i] <= 'Z' && arr[i] >= 'A') {
                    cur = cur + arr[i]; // 拿到压缩字符
                }
            }
            // 遍历次数解压,得到解压后的字符串 result
            while (num) {
                result = cur + result;
                num--;
            }
			
			//  这三句话比较麻烦,我的思路是先把字符转为数组,利用splice方法,例如先删除 [2|CA], 然后插入CACA,就是替换操作了。
            arr = arr.split("");
            arr.splice(begin, end + 1 - begin, result);
            arr = arr.join("");
			
			 // 为什么需要返回now, 是为了让遍历从替换后的字符开始重新寻找括号,然后直到全部替换完!!!
		// arr :  HG[3|BCACA]F
            return { arr, now: begin + result.length }
        }
        var unzip = function (str) {
            let stack = [];
            let begin = 0;
            let i = 0;
            let len =  str.length;
            // 开始使用的for循环来遍历,发现不好更改遍历的值 i ,换成while了。
            while (i < len) {
                if (str[i] == ']') {
                    begin = stack.pop(); // 出栈顶
                    const { arr, now } = getStr(begin, i, str); // 得到替换的最新字符串,
                    str = arr; // 更新字符串
                    i = now - 1; // 让i从替换后的位置开始遍历
                } else if (str[i] == '[') {
                    stack.push(i); // 入栈左括号
                }
                i++;
            }
            return str  // 得到的就是解压缩后的字符串
            // "HGBCACABCACABCACAF"
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那就可爱多一点点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值