Leetcode 394. Decode String 展开字符串的java实现(递归与非递归)

Leetcode 394. Decode String 展开字符串的java实现(递归与非递归)

让我们先看看题吧!Given an encoded string, return its decoded string.

The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k 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 or 2[4].

Example 1:

Input: s = “3[a]2[bc]”
Output: “aaabcbc”
Example 2:

Input: s = “3[a2[c]]”
Output: “accaccacc”
Example 3:

Input: s = “2[abc]3[cd]ef”
Output: “abcabccdcdcdef”
Example 4:

Input: s = “abc3[cd]xyz”
Output: “abccdcdcdxyz”

这一道题其实就是给我们一个用方括号和数字包装的字符串,然后要根据方括号前面的数字来展开后面括号内的内容。一般想到这种自后向前的需求,我们都会想到利用stack的先进后出的特性来处理。我们维护一个栈来存入我们遍历当前字符串,如果遇到数字则记录数字,遇到前方括号就把数字压入栈中,遇到字符压入栈中,遇到后方括号就把当前数组中遇到第一个数字之前的所有字符串弹出组成字符串,再弹出数字进行复制,最后再压入栈中,直到栈中没有任何元素。让我们看看这种非递归的方式用java是怎么实现的吧。

class Decode{
    public String decodeString(String s) {
        Stack<Object> stack = new Stack<Object>();
    	int number = 0;
    	for(char c: s.toCharArray()){
        	if(Character.isDigit(c)){
            	number = number * 10 + (c-'0');
        	}else if(c == '['){
            	stack.push(Integer.valueOf(number));
            	number = 0;
        	}else if(c == ']'){
            	String temp = popStack(stack);
            	Integer count = (Integer)stack.pop();
            	while(count > 0){
                	stack.push(temp);
                	count--;
            	}
        	}else{
            	stack.push(String.valueOf(c));
        	}
    	}
    	return popStack(stack);
    }
    String popStack(Stack<Object> stack){
    	Stack<String> container = new Stack<String>();
    	while(!stack.empty() && (stack.peek() instanceof String)){
        	container.push((String)stack.pop());
    	}
    	StringBuilder sb = new StringBuilder();
    	while(!container.empty()){
        	sb.append(container.pop());
    	}
    	return sb.toString();
 	}
}

利用栈的实现逻辑其实是非常简单的,但是代码会稍微有点多,但是好处就是不会因为包装层数过多而像递归法一样触发stackoverflow的问题,因为我们申明和维护的stack其实内存都是在heap空间中开辟的

再让我们看看递归的实现吧,递归的实现其实稍微容易一些,我们用一个全局变量来记录我们在字符串中遍历的位置,如果遇到前方括号就进入递归然后返回一个字符串,在根据之前记录的数字进行复制即可。

class Decode{
	int i;
	public String decodeString(String s){
		i = 0;
		return decode(s);
	}
	private String decode(String s){
		StringBuilder sb = new StringBuilder();
		int cnt;
		int n = s.length();
		while(i < n && s.charAt(i) != ']'){
			if(Character.isDigit(s.charAt(i)){
				cnt = 0;
				while(i < n && s.charAt(i) != ']'){
					cnt = cnt* 10 +s.charAt(i++)-'0';
				}
				i++;
				String tmp = decode(s);
				i++;
				while(cnt-- >0){
					sb.append(tmp);
				}
			}else{
				sb.append(s.charAt(i));
				i++;
			}
		}
		return sb.toString();
	}
}

递归的实现来说代码相对要少很多,也是遇到数字就记录数字,遇到方括号就在当前指针出递归进行计算,得到当前方括号内的字符串,然后和重复前面记录数组的遍数加入到Stringbuilder中即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值