2020-03-27
字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例:
- s = "3[a]2[bc]", 返回 "aaabcbc".
- s = "3[a2[c]]", 返回 "accaccacc".
- s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
题解:
思路1: 递归
暴力的一层一层解开[]
var decodeString = function (s) { let fn = (k, str) => { let result = ''; // 要返回的字符串 let l, r; // 记录左右括号的位置 while (str.indexOf('[') > -1) { // 当当前字符串还有[时 继续处理字符串 let tmp = 1; // 临时变量 记录当前是否找到闭合的[] for (let i = 0; i < str.length; i++) { // 循环字符串 if (str[i] === '[') { // 当为[时记录l的位置 l = i; } else if (str[i] === ']') { // 当第一次出现 ] 时, tmp设为0 也就是找到了第一个闭合的[] tmp = 0; r = i; } else continue; if (tmp === 0) { // 当找到了闭合的[]时 ,l, r 分别记录的是[]的左右位置 let j = 1; // 记录[前面几位是数字 while (/[0-9]/.test(str[l - (j + 1)]) && l - j >= 0) { j++ // 如果[前面一直是数字,则继续往前找 } const k = parseInt(str.slice(l - j, l)); // k是[前面数字的大小 let sonStr = str.slice(l + 1, r); // sonStr是[]之间的字符串 str = str.slice(0, l - j) + fn(k, sonStr) + str.slice(r + 1); // 传入的字符串等于 数字左侧的 + []之间和k乘积之后的 + ]之后的 break; // 每处理完一个[], break出去继续找下一个 直到str中没有[] } } } for (let i = 0; i < k; i++) { // k是倍数,要把结果循环k次 result += str; } return result; // result是每一个[]处理之后的结果 } return fn(1, s); // s传入 相对于 1[s]的类型 };
思路2: 栈+深度优先搜索
用出栈入栈的思维解开[]
var decodeString = function (s) { let stock = [], res = '', multi = 0; // stock是辅助栈 for (let c of s) { // 遍历字符串 s 中每个字符 c; if (c === '[') { // 当 c 为 [ 时,将当前 multi 和 res 入栈,并分别置空置 0 // 记录此 [ 前的倍数 multi 至栈,用于发现对应 ] 后,获取 multi × [...] 字符串 // 记录此 [ 前的临时结果 res 至栈,用于发现对应 ] 后的拼接操作; stock.push([multi, res]); // 进入到新 [ 后,res 和 multi 重新记录。 multi = 0; res = ''; } else if (c === ']') { // 当 c 为 ] 时,stack 出栈,拼接字符串 res = last_res + cur_multi * res,其中: let tmp = stock.pop(); const last_res = tmp[1]; // last_res是上个 [ 到当前 [ 的字符串,例如 "3[a2[c]]" 中的 a; let cur_multi = tmp[0]; // cur_multi是当前 [ 到 ] 内字符串的重复倍数,例如 "3[a2[c]]" 中的 2。 let ss = res; // ss记录循环后的res while(cur_multi > 1) { ss += res; cur_multi--; } res = last_res + ss; // res变为 上一次存入栈中的last_res拼接循环后的res } else if(/[0-9]/.test(c)) { multi = multi * 10 + parseInt(c); // 当 c 为数字时,将数字字符转化为数字 multi,用于后续倍数计算; } else { res += c; // 当 c 为字母时,在 res 尾部添加 c; } } return res; }
来源:https://www.cnblogs.com/lanpang9661/p/12579917.html