394. Decode String


July-17-2019

一开始用Stack做的,来回倒腾:
不是右括号进栈
右括号的话就开始POP找左括号,找到就有了需要重复的String,然后看重复几次,重复完了司塞回去继续。
有很多edge case忽略了,比如digit大于10;经常要reverse之类的

class Solution {
    public String decodeString(String s) {
        ArrayDeque<Character> stack = new ArrayDeque<>();
        int i = 0;
        StringBuilder res = new StringBuilder();
        while (i < s.length()) {
            char c = s.charAt(i);
            if (c != ']') {
                stack.push(c);
            } else {
                StringBuilder tempSb = new StringBuilder();
                char tempC = stack.pop();
                while (tempC != '[') {
                    tempSb.append(tempC);
                    tempC = stack.pop();
                }
                int repeatCount = getRepeatCount(stack);
                String tempStr = tempSb.toString();

                for (int j = 1; j < repeatCount; j ++) {
                    tempSb.append(tempStr);
                }
                tempStr = tempSb.reverse().toString();
                for (int j = 0; j < tempStr.length(); j ++) {
                    stack.push(tempStr.charAt(j));
                }
            }
            i ++;
        }
        while (!stack.isEmpty()) {
            res.append(stack.pop());
        }
        return res.reverse().toString();
    }
    
    private int getRepeatCount(ArrayDeque<Character> stack) {
        StringBuilder sb = new StringBuilder();
        while (!stack.isEmpty() && Character.isDigit(stack.peek())) {
            sb.append(stack.pop());
        }
        return Integer.valueOf(sb.reverse().toString());
    }
}

看以前自己写的答案,可以不用STACK直接干,或者说用RECURSION来替代Stack。
找到左括号之后一直往右找到和它同级的右括号。
3[abc4[de]]来说:
DECODE(3[abc4[de]]) = > DECODE(3[DECODE(abc4[de])])
找到第一层3[abc4[de]]把里面的abc4[de]直接传入下层decode()做recursion call,回来再乘以重复的次数。
其实abc = 1[a]1[b]1[c],相当于1不用算了

class Solution {
    public String decodeString(String s) {
        StringBuilder res = new StringBuilder();
        
        int i = 0;
        while (i < s.length()) {
            char c = s.charAt(i);
            if (Character.isDigit(c)) {
                
                // get repeat times
                int repeatCount = c - '0';
                i ++;
                while (Character.isDigit(s.charAt(i))) {
                    repeatCount = repeatCount * 10 + s.charAt(i ++) - '0';
                }
                
                // remember start position of string taht goes to next level recursion call
                int startIndex = ++i;

                // find end position of string that goes to next level recursion call
                // based on open parenthesis
                int openParentheses = 1;
                while (openParentheses != 0) {
                    char tempChar = s.charAt(i);
                    if (tempChar == '[') {
                        openParentheses ++;
                    } else if (tempChar == ']') {
                        openParentheses --;
                    }
                    i ++;
                }
                i --;
                // goes to next call and report X times
                String innerStr = decodeString(s.substring(startIndex, i));
                for (int j = 0; j < repeatCount; j ++) {
                    res.append(innerStr);
                }
                i ++;
            } else {
                res.append(c);
                i ++;
            }
        }
        return res.toString();
    }
}

三刷
12-Jan-2017

可以确定思路是DFS+Stack。
可以纯用STACK手动操作,也可以通过dfs的memory stack来记录 which is much easier..

对于一个String:
232[ vSDFSADS ]
只要确定前面的数字 232,和跟随他的大括号的范围就行了。
当然大括号里面可能嵌套别的 数字[fsdf] 这样的组合,所以关键是定位跟随大括号的位置。
也很简单,左边括号数量 = 右边括号数的时候,就是该进入next depth的范围。

Time: 指数级别的? 范围定位在最后的话,搜索过去就算遍历过一次这个pattern了。。但是这个pattern还要进入下一层。。

Space: memory stack..depends on how deep our search goes

public class Solution {
    public String decodeString(String s) {
        if  (s.length() <= 1) return s;
        
        int i = 0; 
        StringBuilder res = new StringBuilder();
        
        while (i < s.length()) {
            char c = s.charAt(i);
            // find a digit, meaning we're gonna go deeper
            if (Character.isDigit(c)) {
                // get digit
                int num = 0;
                while (i < s.length() && Character.isDigit(c)) {
                    num = num * 10 + c - '0';
                    c = s.charAt(++i);
                }
                
                // search for index of the pattern which goes to next depth
                int start = ++i;
                int leftNum = 1;
                
                while (i < s.length()) {
                    if (s.charAt(i) == '[') {
                        leftNum ++;
                    } else if (s.charAt(i) == ']') {
                        if (--leftNum == 0) {
                            break;
                        }
                    }
                    i++;
                }
                
                // s.substring(start, i) goes to next level
                String tempStr = decodeString(s.substring(start, i));
                
                // repeat num times
                while (num > 0) {
                    res.append(tempStr);
                    num --;
                }
                i ++;
                
            } else if (Character.isAlphabetic(c)) {
                // we ain't do shit if it's simply a letter.. and not in []
                res.append(c);
                i ++;
            }
        }
        
        return res.toString();
    }
}

posted @ 2017-01-13 03:22  哇呀呀..生气啦~  阅读(245)  评论(0编辑  收藏  举报