• 力扣算法:字符串解码


    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/decode-string

    原题:

    给定一个经过编码的字符串,返回它解码后的字符串。

    编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

    你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

    此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

    示例 1:

    输入:s = "3[a]2[bc]"
    输出:"aaabcbc"
    示例 2:

    输入:s = "3[a2[c]]"
    输出:"accaccacc"
    示例 3:

    输入:s = "2[abc]3[cd]ef"
    输出:"abcabccdcdcdef"
    示例 4:

    输入:s = "abc3[cd]xyz"
    输出:"abccdcdcdxyz"

    解题思路:

        首先需要使用一个栈,用来储存 [  的位置,遇到则进, 当遇到  ]  时说明 这两个位置之间的内容是会重复多次出现的。 而且 [  的前边的几位可能是数字,根绝这些信息就能准确的找到 重复次数,重复内容,然后根据字符串截取,将这些内容拼接到原字符串。

       因为会遇到嵌套的情况,所以当 遇到 ]  时进行了上述操作。将 【】 的内容和前边的数字替换为相应内容之后,需要判断栈内是否仍然有元素,如果有则说明是嵌套结构,需要将循环指针重新指向栈顶元素的下一位。再次扫描。如果栈空,则从头开始扫描。知道没有遇到符号为止。

    源码如下:

    public String decodeString(String s) {
            Stack<Integer> stack=new Stack<>();  //储存[ 的位置
            int start=0;  //记录 [ ] 内第一个元素的位置
            int end=0;    //记录 对应的 ] 的位置
            int num=0;    //记录重复部分需要出现的次数
            int nums=0;   //记录次数的第一个字符出现的位置
            int nume=0;   //记录次数的最后一个字符 [   方便截取
            for(int i=0;i<s.length();i++){
                char c=s.charAt(i);
                if(c=='['){             //遇到 [  则入栈
                    stack.push(i);
                }
                if(c==']'){
                    start=stack.pop();   //遇到 ] 出栈,并获取栈顶的 [ 的位置
                    end=i;
                    nume=start;
                    nums=start-1;
                    while (nums-1>=0&&s.charAt(nums-1)>='0'&&s.charAt(nums-1)<='9')   //判断 [ 之前的是否为数字,并找到数字起点
                        nums--;
    
                    num=Integer.parseInt(s.substring(nums,nume));   //计算出数字,即重复部分出现的次数
    
                    String mystr="";    //重复部分拼接
                    for(int j=0;j<num;j++){
                        mystr+=s.substring(start+1,end);   //截取对应部分拼接
                    }
                    s=s.substring(0,nums)+mystr+s.substring(end+1,s.length());  //将原来字符串的  3[a]  部分修改为 aaa
                    if(!stack.isEmpty())    //如果栈内仍然有元素,则需要将指向重新设定为 栈顶元的下一个位置
                        i=stack.peek()+1;
                    else     //栈空则从头开始扫描
                        i=0;
                }
            }
    
            return s;
        }

    PS:目前这块代码消耗时间空间较大,优化的思路是 可以使用 StringBuffer 来替代String  

    因为里边每次涉及到字符串拼接,字符串的变化,都会申请新的空间,如果使用stringbuffer 可以在原基础上修改,比较好用。

  • 相关阅读:
    Ext Js MVC系列二 利用Application和Viewport进行应用程序初始化和页面布局
    LINQ to Sql系列一 增,删,改
    Ext Js MVC系列一 环境搭建和MVC框架整体认识
    LINQ to Sql系列四 性能优化总结
    SQL基础回顾系列一 单表查询(select语句)
    JSON详解
    公用类库(4) 缓存操作类CacheUtil
    架构设计考虑的问题(出自代码大全II)
    .net自动更新组件Ant
    .net socket在win2008下的吞吐性能报告
  • 原文地址:https://www.cnblogs.com/wys-373/p/13299992.html
Copyright © 2020-2023  润新知