来源:力扣(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 可以在原基础上修改,比较好用。