[LeetCode] 394. Decode String 解题报告

Given an encoded string, return it's decoded string.

The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note thatk is guaranteed to be a positive integer.

You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.

Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a or2[4].

Examples:

s = "3[a]2[bc]", return "aaabcbc".
s = "3[a2[c]]", return "accaccacc".
s = "2[abc]3[cd]ef", return "abcabccdcdcdef".

这一题思维难度不大,很显然是考察stack的使用,主要是注意细节上的处理,如果一些情况考虑的不够周到,debug可能会话费比较多的时间。

思路:

使用两个stack,一个(1)用来存储系数,一个(2)用来存储字母和括号。用一个循环遍历整个字符串就可以了,基本思路和polish notation非常类似。

按顺序,一个一个的字符遍历,具体方式如下:

  1. 遇到系数,将系数入栈1(这里的系数可能是多位的,所以要一直检测到数字字符结束,比如:10000);
  2. 遇到左括号[,入栈2;
  3. 遇到字符,将后面所有字符入栈2,比如:接下来在字符串是,aaab2[ac....,则将aaab入栈;
  4. 遇到右括号],这一步就稍微有点复杂。循环出栈2,直到遇到左括号[,就停止出栈。比如:stack2=["x","[","a","b"],则将ba[,按顺序出栈,然后把里面的字符拼接起来,括号去掉,拼接得到的字符是“ab”。然后,将栈1的一个系数出栈(假设系数为3),根据系数循环复制相同的字符串,得到“ababab”,再把复制后的字符再次入栈2。此时栈2的内容是,stack2=["x","ababab"]。
  5. 直到遍历结束,按顺序拼接栈2中的所有字符串,返回结果即可。
代码如下,复杂度大致是O(N),但实际消耗要高于N:

public class Solution {
	public String decodeString(String s) {
		Stack<Integer> staNumbers = new Stack<>();
		Stack<String> staMarks = new Stack<>();
		char[] cArr = s.toCharArray();
		for (int i = 0; i < cArr.length; i++) {
			char c = cArr[i];
			if (c >= '0' && c <= '9') {
				// if the number is like 10000, which is more than 1 digit
				StringBuilder sbNumber = new StringBuilder();
				while (i < cArr.length && cArr[i] >= '0' && cArr[i] <= '9') {
					sbNumber.append(cArr[i]);
					i++;
				}
				i--;
				staNumbers.push(Integer.parseInt(sbNumber.toString()));
			} else if (c == '[') {
				staMarks.push("[");
			} else if (c == ']') {
				StringBuilder sbNew = new StringBuilder();
				while (true) {
					StringBuilder sb = new StringBuilder(staMarks.pop());
					if (sb.toString().equals("[")) {
						break;
					} else {
						sbNew.insert(0, sb);
					}
				}
				int nLoopTime = staNumbers.pop();
				StringBuilder sbNewNew = new StringBuilder();
				for (int j = 0; j < nLoopTime; j++) {
					sbNewNew.append(sbNew);
				}
				staMarks.push(sbNewNew.toString());
			} else {
				StringBuilder sb = new StringBuilder();
				while (i < cArr.length && cArr[i] >= 'a' && cArr[i] <= 'z') {
					sb.append(cArr[i]);
					i++;
				}
				staMarks.add(sb.toString());
				i--;
			}
		}
		// get all string in staMarks
		StringBuilder sb = new StringBuilder();
		while (!staMarks.isEmpty()) {
			sb.insert(0, staMarks.pop());
		}
		return sb.toString();
	}

}

我把代码中Stack2的类型从String改为StringBuilder以后,发现还变慢了。我推测是因为leetcode的测试用例可能非常极端(如:a[a[a[a[a[a[a[a[a]b]b]b]b]b]......),需要入栈的内容太多,String和StringBuilder对象都很多的情况下,其实没有太大的性能提升。并且,String的某些地方可能还进行了优化,所以这个改动不但没有必要,可能还造成了性能的下降。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值