394. Decode String [Medium]

自己想到的方式就是递归和栈两种

因为要获得一对"[]"中间的字符串内容,用stack1来保存遍历了的字符序列(stack1的类型是Stack<Character>)每遇到']'就从stack1中pop出元素直到遇到'[',就能获得对应的一对"[]"及其间的元素(元素序列是倒序,所以要用sb.insert(),不能用sb.append()),再pop一个元素就是其间元素应该重复的次数,按次数重复后就得到decoded substring;

将decoded substring放入另一个栈stack2保存(stack2的类型是Stack<String>),向stack1中push一个字符'-'表示此处有一个decoded substring,然后继续向后遍历,直到整个字符串被遍历完;

最后将stack1中的字符逐个pop出来,insert到一个StringBuilder里组成结果(如果遇到'-',不是直接insert '-',而要insert从stack2中pop出来的decoded substring)。

递归

因为题目涉及很多重复子单元的重复嵌套,每个单元是一个encoded substring,递归方法能decode一个encoded substring,每当遇到数字,说明当前的encoded substring中还嵌套了encoded substring,调用自身来decode、append返回的字符串、遍历到嵌套的encoded substring的尾部,再继续向后遍历;

decode过程中,一旦遇到']'字符就停止,此时已经decode到了当前的encoded substring的结尾(结尾之前不会遇到']',即使中间有嵌套的encoded substring,它的']'会在遇到数字字符的那个判断中的while循环里被走完);如果arr走完,也停止decode,只有当s不是一个encoded substring的情况下(例如,s为"ab2[c]"或"2[abc]d"这种,而不是"2[ab2[c]]"这种)的第一次调用可能出现这个情况,其他时候的decode都应该是在']'处结束。

/**
 * 自己的代码1,用stack来获取一对"[]"中间的字符串内容
 * 感觉有点繁琐
 * Runtime: 2 ms, faster than 43.37%
 * Memory Usage: 39.1 MB, less than 12.56%
 */
class Solution {
    
    public String decodeString(String s) {
        LinkedList<Character> main = new LinkedList(); // store the sequence of traversed characters
        LinkedList<String> subs = new LinkedList(); // store the decoded substrings
        
        // decode "s"
        for (char curr : s.toCharArray()) {
            if (curr != ']') {
                main.push(curr);
            } else { // decode the nearest substring
                StringBuilder sub = new StringBuilder();
                int times = 0;
                while (!main.isEmpty()) {
                    char c = main.pop();
                    if (c == '[') { // reach the start of the encoded substring
                        int digits = 0;
                        while (!main.isEmpty() && main.peek() >= '0' && main.peek() <= '9') { // get the times the substring should be repeated
                            times += (main.pop() - '0') * Math.pow(10, digits++);
                        }
                        break;
                    }
                    sub.insert(0, c == '-' ? subs.pop() : c);
                }
                String subString = sub.toString();
                while (times-- > 1) {
                    sub.append(subString);
                }
                subs.push(sub.toString()); // store the decoded substring
                main.push('-'); // mark that a decoded substring should be taken from Stack "subs"
            }
        }
        
        // form "res" by combining all the characters and decoded substrings in sequence
        StringBuilder res = new StringBuilder();
        while (!main.isEmpty()) { 
            char c = main.pop();
            res.insert(0, c == '-' ? subs.pop() : c);
        }
        return res.toString();
    }
    
}
/**
 * 自己的代码2,递归
 * Runtime: 0 ms, faster than 100.00%
 * Memory Usage: 39 MB, less than 12.45%
 */
class Solution {
    
    public String decodeString(String s) {
        char[] arr = s.toCharArray();
        return decoder(arr, 0, 1); // consider "s" a encoded string that start at index 0 and should be repeated 1 time
    }
    
    private String decoder(char[] arr, int idx, int times) {
        StringBuilder sb = new StringBuilder();
        for (int i = idx; i < arr.length && arr[i] != ']'; i++) { // when i reach the end of arr(the encoded string is "s"), or arr[i] is ']'(the encoded string is "s"'s substring), current decoding is done
            if (arr[i] <= '9' && arr[i] >= '0') { // encounter an encoded substring
                // decode the substring and append it to sb
                int subTimes = 0;
                while (arr[i] <= '9' && arr[i] >= '0') {
                    subTimes = subTimes * 10 + arr[i++] - '0';
                }
                sb.append(decoder(arr, i + 1, subTimes));
                // find the position after the encoded part
                LinkedList<Character> stack = new LinkedList();
                stack.push('[');
                while (!stack.isEmpty()) {
                    i++;
                    if (arr[i] == '[') {
                        stack.push('[');
                    } else if (arr[i] == ']') {
                        stack.pop();
                    }
                }
            } else {
                sb.append(arr[i]);
            }
        }
        
        String sub = sb.toString();
        while (times-- > 1) {
            sb.append(sub);
        }
        return sb.toString();
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值