• 241. Different Ways to Add Parentheses


    题目:

    Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are+- and *.


    Example 1

    Input: "2-1-1".

    ((2-1)-1) = 0
    (2-(1-1)) = 2

    Output: [0, 2]


    Example 2

    Input: "2*3-4*5"

    (2*(3-(4*5))) = -34
    ((2*3)-(4*5)) = -14
    ((2*(3-4))*5) = -10
    (2*((3-4)*5)) = -10
    (((2*3)-4)*5) = 10

    Output: [-34, -14, -10, -10, 10]

    链接: http://leetcode.com/problems/different-ways-to-add-parentheses/

    题解:

    这题说是Different Ways to add parentheses,其实意思就是忽略运算符的优先级来计算算式。对此我们的解法是: 在算式valid的条件下,只要遇到运算符,我们就计算出左侧的数和右侧的数,然后根据这个运算符来得到结果。看discuss的时候发现Stefan Pochmann大神的解法...一行,擦,这哥们魔方还玩得很好,据说得过德国魔方比赛第一,是真牛。

    Time Complexity - O(3n), Space Complexity - O(3n)

    public class Solution {
        public List<Integer> diffWaysToCompute(String input) {
            if(input == null || input.length() == 0)
                return new ArrayList<Integer>();
            List<Integer> res = new ArrayList<>();
            
            for(int i = 0; i < input.length(); i++) {
                char c = input.charAt(i);
                if(c == '+' || c == '*' || c == '-') {
                    List<Integer> l1 = diffWaysToCompute(input.substring(0, i));
                    List<Integer> l2 = diffWaysToCompute(input.substring(i + 1));
                    for( int x : l1) {
                        for(int y : l2) {
                            if(c == '+')
                                res.add(x + y);
                            else if(c == '-')
                                res.add(x - y);
                            else
                                res.add(x * y);
                        }
                    }
                }
            }
            
            if(res.size() == 0)
                res.add(Integer.valueOf(input));
            return res;
        }
    }

    二刷:

    卡住了,一刷一定又是看答案过的...这道题,我们仔细阅读一下就会想到能否递归求解。递归的话,要考虑用什么数据结构存, base case是什么, 是否需要回溯等等。

    这道题的主要意思就是我们可以任意加括号来破坏运算符的计算规则,返回所有可能的值。这里很像Unique Binary Search Tree II, 我们需要先递归计算运算符左半边的结果,和运算符右半边的结果,然后使用双重循环,根据运算符来把最终结果加入到结果集res中去。要注意的是递归到最后,我们的base case是没有运算符,只有数字的时候, 这时我们可以直接把这个数加入到结果集里。时间复杂度应该是catalan number,空间复杂度也是指数级。

    Java:

    Time Complexity - O(2n), Space Complexity - O(2n)

    public class Solution {
        public List<Integer> diffWaysToCompute(String input) {
            List<Integer> res = new ArrayList<>();
            if (input == null || input.length() == 0) return res;
            for (int i = 0; i < input.length(); i++) {
                char c = input.charAt(i);
                if (c == '+' || c == '-' || c == '*') {
                    List<Integer> left = diffWaysToCompute(input.substring(0, i));
                    List<Integer> right = diffWaysToCompute(input.substring(i + 1));
                    for (int l : left) {
                        for (int r : right) {
                            if (c == '+') res.add(l + r);
                            else if (c == '-') res.add(l - r);
                            else res.add(l * r);
                        }
                    }
                }
            }
            if (res.size() == 0) res.add(Integer.parseInt(input));
            return res;
        }
    }

    三刷:

    在二刷的基础上加入一个HashMap来存储以前计算过的值,跟滑雪一样属于memorization,速度快了不少。但worst case复杂度仍然是指数级。 还看到有题友用DP来写,并没有看懂...

    Java:

    public class Solution {
        Map<String, List<Integer>> map = new HashMap<>();
        
        public List<Integer> diffWaysToCompute(String input) {
            if (map.containsKey(input)) return map.get(input);
            List<Integer> res = new ArrayList<>();
            if (input == null || input.length() == 0) return res;
            for (int i = 0; i < input.length(); i++) {
                char c = input.charAt(i);
                if (c == '+' || c == '-' || c == '*') {
                    List<Integer> leftNums = diffWaysToCompute(input.substring(0, i));
                    List<Integer> rightNums = diffWaysToCompute(input.substring(i + 1));
                    for (int left : leftNums) {
                        for (int right : rightNums) {
                            if (c == '+') res.add(left + right);
                            else if (c == '-') res.add(left - right);
                            else if (c == '*') res.add(left * right);
                        }
                    }
                }
            }
            if (res.size() == 0) res.add(Integer.parseInt(input));
            map.put(input, res);
            return res;
        }
    }

    Reference:

    https://leetcode.com/discuss/48468/1-11-lines-python-9-lines-c

    https://leetcode.com/discuss/60626/share-a-clean-and-short-java-solution

    https://leetcode.com/discuss/53566/python-easy-to-understand-solution-divide-and-conquer

    https://leetcode.com/discuss/61840/java-recursive-9ms-and-dp-4ms-solution

    https://leetcode.com/discuss/48477/a-recursive-java-solution-284-ms

    https://leetcode.com/discuss/48488/c-4ms-recursive-%26-dp-solution-with-brief-explanation

    https://leetcode.com/discuss/48494/what-is-the-time-complexity-of-divide-and-conquer-method

    https://leetcode.com/discuss/55255/clean-ac-c-solution-with-explanation

    http://stackoverflow.com/questions/13525024/how-to-split-a-mathematical-expression-on-operators-as-delimiters-while-keeping                      <- split by "[-+*]",  not by "[+-*]"

    https://leetcode.com/problems/unique-binary-search-trees-ii/

  • 相关阅读:
    python程序打包,来源于知乎(已验证)
    登录窗体界面设计
    窗体应用常见操作
    MDI窗体应用
    第四单元
    Test3_3——3_20
    TEST3_2
    ff文字省略号
    jQuery 浏览器高度宽度获取
    CSS 单行溢出文本显示省略号...的方法(兼容IE FF)(转)
  • 原文地址:https://www.cnblogs.com/yrbbest/p/5006196.html
Copyright © 2020-2023  润新知