Sunday, August 20, 2017

394. Decode String

三刷 07/2022
Version #1 Stack
自己凭直觉写了一遍,看了一下没有第一次写的时候简洁
用了一个Node Object代表string 和数字
写了一个bug就是因为我只检查stack顶端是不是数字来和当前数字相连,所以遇到2[2[这种情况就会判断成为22
而且我的方法没有利用到“[”的case,直接continue了
其实可以利用“'[”来进行入栈的操作,只有遇到"["才把数字push进去,应该会简单很多

Time O(N)?
?? 2[2[2[2[2[2['a']]]]]
Time Complexity: \mathcal{O}(\text{maxK} \cdot n)O(maxK⋅n), where \text{maxK}maxK is the maximum value of kk and nn is the length of a given string ss. We traverse a string of size nn and iterate kk times to decode each pattern of form \text{k[string]}k[string]. This gives us worst case time complexity as \mathcal{O}(\text{maxK} \cdot n)O(maxK⋅n).

Space O(N)

Runtime: 2 ms, faster than 58.11% of Java online submissions for Decode String.
Memory Usage: 41.8 MB, less than 74.45% of Java online submissions for Decode String.

class Solution {
    class Node {
        public int val;
        public String str;
        public boolean isNum;
        public Node(int val) {
            this.val = val;
            this.isNum = true;
        }
        
        public Node(String str) {
            this.str = str;
        }
    }
    public String decodeString(String s) {
        Stack<Node> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isDigit(c)) {
                int val = c - '0';
                if (!stack.isEmpty() && stack.peek().isNum && Character.isDigit(s.charAt(i - 1))) {
                    val += stack.pop().val * 10;
                }
                stack.push(new Node(val));
                continue;
            }
            if (c == '[') {
                continue;
            }
            if (c == ']') {
                StringBuilder sb = new StringBuilder();
                String str = stack.pop().str;
                // System.out.printf("str=%s\n", str);
                int cnt = stack.pop().val;
                while (cnt-- > 0) {
                    sb.append(str);
                }
                pushString(stack, sb.toString());
                continue;
            }
            pushString(stack, "" + c);
        }
        return stack.pop().str;
    }
    
    private void pushString(Stack<Node> stack, String str) {
        String prev = "";
        if (!stack.isEmpty() && !stack.peek().isNum) {
            prev = stack.pop().str;
        }
        stack.push(new Node(prev + str));
    }
}


二刷
53.83 %
class Solution {
    public String decodeString(String s) {
        if (s == null || s.length() == 0) {
            return s;
        }
        Deque<Integer> nums = new ArrayDeque<>();
Deque<String> chars = new ArrayDeque<>();
        int i = 0;
        char curr;
        StringBuilder sb = new StringBuilder();
        while (i < s.length()) {
            curr = s.charAt(i);
            if (Character.isDigit(curr)) {
                int num = curr - '0';
                while (i + 1 < s.length() && Character.isDigit(s.charAt(i + 1))) {
                    num = num * 10 + s.charAt(i + 1) - '0';
                    i++;
                }
                nums.addFirst(num);
            } else if (curr == '[') {
                chars.addFirst(sb.toString());
                sb.setLength(0);
            } else if (curr == ']') {
                int count = nums.isEmpty() ? 1 : nums.removeFirst();
                String repeat = sb.toString();
                while (count-- > 1) {
                    sb.append(repeat);
                }
                sb.insert(0, chars.removeFirst());
            } else {
                sb.append(curr);
            }
            i++;
        }
        return sb.toString();
    }
}

一刷
感觉写一个Stack<Object>也是可以的,但是每次要判断的太多,没有必要
两个Stack一个是count一个是StringBuilder
遇到"["就把之前的StringBuilder和数字压栈
遇到"]"就pop且和之前的parent StringBuilder连在一起

这里的initialize是初始化一个最开始的容器StringBuilder,放最终的结果然后return
如果没有初始化的容器而只当遇到"["才new StringBuilder的话很显然是不对的

因为edge case比较少所以一遍就写过了

40.18 %
class Solution {
    public String decodeString(String s) {
        if (s == null) return s;
     
        Stack<StringBuilder> sStack = new Stack<>();
        Stack<Integer> cStack = new Stack<>();
        int count = 0;
        StringBuilder curr = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isDigit(c)) {
                count = count * 10 + Character.getNumericValue(c);
            } else if (c == '[') {
                cStack.push(count);
                count = 0;
                sStack.push(curr);
                curr = new StringBuilder();
            } else if (c == ']') {
                int repeat = cStack.pop();
                StringBuilder prev = sStack.pop();
                while (repeat-- > 0) {
                    prev.append(curr);
                }
                curr = prev;
            } else {
                curr.append(c);
            }
        }
        return curr.toString();
    }
}


No comments:

Post a Comment