zoukankan      html  css  js  c++  java
  • 394.字符串解码

    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;
    }
  • 相关阅读:
    Android中fragment之间和Activity的传值、切换
    javascript--经典实例锦集
    Android中ListView动态加载数据
    Android开发之调用系统图库及相机
    Android 相机开发详解
    RTSP实例解析
    【Android UI设计与开发】第18期:滑动菜单栏(三)SlidingMenu动画效果的实现
    js 第二小步
    JavaScript初步+基本函数
    javaweb实战开始
  • 原文地址:https://www.cnblogs.com/lanpang9661/p/12579917.html
Copyright © 2011-2022 走看看