LeetCode[241. Different Ways to Add Parentheses] 难度[medium]

题目

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 *.
意思就是给定一条表达式,可以在任意地方加括号改变运算顺序,求可能出现的结果。

算法分析:

这道题主要用到分治的思想,最直接的想法就是对于每个运算符,都把等式分成左右两半,再把两边可能出现的所有结果使用这个运算符运算出结果,如此递归下去,当递归到剩下一个数字就直接返回这个数字,这是未优化的版本。
代码如下(未优化)

class Solution {
public:
    vector<int> diffWaysToCompute(string str) {
        vector<int> result,r1,r2;
        string s1,s2;
        bool isNum = true;
        int n = str.size();
        for(int i=0; i<n; ++i){
            if(str[i]=='+'||str[i]=='-'||str[i]=='*'){
                isNum = false;
                s1 = str.substr(0,i);
                s2 = str.substr(i+1,n-i-1);
                r1 = diffWaysToCompute(s1);
                r2 = diffWaysToCompute(s2);
                int n1 =r1.size(), n2 = r2.size();
                for(int j=0;j<n1; ++j){
                    for(int h=0;h<n2;++h){
                        if(str[i]=='+') result.push_back(r1[j]+r2[h]);
                        if(str[i]=='-') result.push_back(r1[j]-r2[h]);
                        if(str[i]=='*') result.push_back(r1[j]*r2[h]);
                    }
                }
            }
        }
        if(isNum){
            result.push_back(getNum(str));
        }
        return result;
    }
private:
    int getNum(string s){
        int n = s.size();
        int result;
        for(int i=0; i<n;++i){
            result *= 10;
            result += s[i]-'0';
        }
        return result;
    }
};

这样做在LeetCode上是可以AC的,但效率却不高,因为在递归过程中有许多算重复的式子,比如1+2*3+4, 在(1+2*3)里面要算1+2,在(1+2)里面又要重复算一遍。
优化:这样做之所以慢主要是由于要重复计算同样的等式造成的,所以我们可以用一个map把等式和结果一一对应起来,用空间换取时间,从而提高效率。另外,由于本题输入的是一个字符串,每次运算都要把字符串编程数字,一个数字要重复转换多次,可以提前先把整条式子都转换成数字,从而达到优化效果。
代码实现如下:

class Solution {
public:
    vector<int> diffWaysToCompute(string str) {
        vector<int> digit,result;
        int num = 0;
        int n = str.size();
        for(int i=0; i<n; ++i){
            if(isdigit(str[i])){
                num *= 10;
                num += str[i]-'0';
            }
            else{
                digit.push_back(num);
                num = 0;
                digit.push_back(str[i]);
            }
        }
        digit.push_back(num);
        int size = digit.size();
        result = getResult(digit,0,size-1);

        return result;
    }

private:
    map<int,vector<int> > record;
    vector<int> getResult(vector<int> &digit,int low,int high) {
        int n = digit.size();
        int key = low*(n+1)+high;
        if(record.find(key)!=record.end())
            return record[key];
        vector<int> result,r1,r2;
        if(low+1==high || low==high){
            result.push_back(digit[low]);
        }
        for(int i=low+1; i<high; i+=2){
                r1 = getResult(digit,low,i);
                r2 = getResult(digit,i+1,high);
                int n1 =r1.size(), n2 = r2.size();
                for(int j=0;j<n1; ++j){
                    for(int h=0;h<n2;++h){
                        if(digit[i]=='+')   result.push_back(r1[j]+r2[h]);
                        if(digit[i]=='-')   result.push_back(r1[j]-r2[h]);
                        if(digit[i]=='*')   result.push_back(r1[j]*r2[h]);
                    }
                }
        }
        record[key] = result;
        return result;
    }

};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值