zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    [Web] 被遗忘的知识点 XHTML
    [项目实践进阶篇] Android 项目中使用Ant + Groovy能干什么?
    使用Ant,第1部分:将Ant脚本引入Java项目
    [Web] 被遗忘的知识点 JavaScript加载管理最佳实践
    [Web] 被遗忘的知识点 iFrames(HTML)过时了没有?
    Android ProGuard
    stream.js
    GUID(全球唯一标识符)
    解析算术表达式
    LCG(linear congruential generator)伪随机数生成器
  • 原文地址:https://www.cnblogs.com/yrbbest/p/5006196.html
Copyright © 2011-2022 走看看