241. Different Ways to Add Parentheses

来源:互联网 发布:网络电视直播apk下载 编辑:程序博客网 时间:2024/06/06 12:48

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]

s思路:
1. 看起来很复杂的题,为啥acceptance rate 41%? 要列举所有可能情况,套路是有的,用backtracking=for+recursive
2. backtrack的问题,有重复,需要破除重复!
3. 看了hint,用divide-and-conquer,即:DAC,但是这个问题确实选择用DAC比BT(backtracking)好理解,得分问题了。下面分别说一下思路和对比:
4. 对比:以”1-2-3-4-5”为例,如果用backtrack来做,则是在遇到符号的时候,还是说DAC容易些,越想越觉得是用DAC,backtrack不适合这个题。
5. 所谓DAC,就是把这个问题划分成若干小问题,分别处理小问题,然后合起来就是完整的问题。这一点,竟让我想起了概率求和的公式,为了计算事件发生总概率,但是注意到该事件可以容易划分成若干事件,且相互独立,那么就分别计算,然后相加。这题也是一样,由于添加括号总是发生在符号两边,那么可以以每个符号为分界线,把等式划分成左右两部分,分别求左边的表达式的可能结果和右边表达式的可能结果,然后根据符号对两个集合的结果再运算;如下图。把所有情况列举完成就可以得到全部结果了。
这里写图片描述
6. backtracking一半从左往右来遍历,而这道题只遍历符号,然后就把问题分成两个独立的问题。我发现,如果能把问题分割成两个问题,那就妥妥的用DAC,这题也不例外。

  1. 最后谈谈重复的问题:还是看上图,碰到第一个减号时,需要分别去得到左边和右边的不同结果,左边是1,右边是(2-3-4-5),而求(2-3-4-5)由需要分成小问题:包括(2)-(3-4-5),(2-3)-(4-5)和(2-3-4)-(5);然后碰到第二减号时,则需要计算左边(1-2)和右边(3-4-5)的结果。注意:(3-4-5)计算了两次,因此重复了!如何去重复呢?把结果存在map中然后每次计算前,查询是否计算过,要是计算过直接返回结果,否则就计算,然后把计算结果保存在map中。
  2. 这个重复问题,是backtrack中也经常遇到的情况。这不得不说是这种方式的弊端,因为存在同一层的遍历和不同层遍历都会遍历同一个元素!
//方法1:DAC,要习惯简写,divide-and-conquer.一次成功!class Solution {public:    vector<int> helper(string input,unordered_map<string,vector<int>>&mm){        //        if(mm.count(input)) return mm[input];        vector<int> res;        for(int i=0;i<input.size();i++){            if(input[i]=='+'||input[i]=='-'||input[i]=='*'){                vector<int> left=helper(input.substr(0,i),mm);                vector<int> right=helper(input.substr(i+1),mm);                for(int j=0;j<left.size();j++){                    for(int k=0;k<right.size();k++){                        int cur=0;                        if(input[i]=='+') cur=left[j]+right[k];                        else if(input[i]=='-') cur=left[j]-right[k];                        else cur=left[j]*right[k];                        res.push_back(cur);                     }                   }                               }           }        if(res.empty()) res.push_back(stoi(input));        mm[input]=res;        return res;    }       vector<int> diffWaysToCompute(string input) {        //        unordered_map<string,vector<int>> mm;        return helper(input,mm);    }};
0 0