282. Expression Add Operators

problem description

Given a string that contains only digits 0-9 and a target value, return all possibilities to add binary operators (not unary) +, -, or * between the digits so they evaluate to the target value.

Example 1:

Input: num = "123", target = 6
Output: ["1+2+3", "1*2*3"]

Example 2:

Input: num = "232", target = 8
Output: ["2*3+2", "2+3*2"]

Example 3:

Input: num = "105", target = 5
Output: ["1*0+5","10-5"]

Example 4:

Input: num = "00", target = 0
Output: ["0+0", "0-0", "0*0"]

Example 5:

Input: num = "3456237490", target = 9191
Output: []

algorithm thought

对于每个能放置操作符的地方,有4种情况。第一种是不放置,然后三种是放置3个不同的操作符。

将情况大概讲出来之后,就知道这里使用回溯法解决问题了。这里问题关键在于如果前面是一个加法,然后碰到一个乘法,如何解决。

这里在回溯的时候,保存前面一个操作的数字值。如果当前是乘法,就将当前值减去或者加上前面的值(相当于回溯到前面),然后将前面的值和当前数字相乘,再让前面值加上或者减去当前值。这是大概的思路。实际实现时候,可以优化。

需要注意的是,如果碰到开头为0的字符串需要处理。这里对要求对c++数字和字符串转化操作熟悉

code

class Solution {
public:
    vector<string> addOperators(string num, int target) {
        vector<string> res;
        string now="";
        help(res,target,num,0,0,now,0);
        return res;
    }
    void help(vector<string>&res,int target,string&num,long pre_value,long value,string&now,int pos){
        if(pos==num.size()&&value==target){
            res.push_back(now);
            return;
        }
        for(int i=pos;i<num.size();++i){
            string t=num.substr(pos,i-pos+1);
            if(t.size()>1&&t[0]=='0')
                continue;
            long va=stol(t);

            if(pos==0){
                help(res,target,num,va,va,t,i+1);
                continue;
            }

            int sz=now.size();
            now.push_back('+');now+=t;
            help(res,target,num,va,value+va,now,i+1);
            now[now.size()-t.size()-1]='-';
            help(res,target,num,-va,value-va,now,i+1);
            now[now.size()-t.size()-1]='*';
            help(res,target,num,pre_value*va,value-pre_value+pre_value*va,now,i+1);
            now.resize(sz);
        }
    }
};

algorithm analysis

回溯法时间复杂度分析比较困难,只需要知道这里是指数级时间复杂度。这里还有一个关键的优化在于对string的处理。我看别的答案直接使用operator +,并且没有使用左值引用减少析构和构造。时间复杂度400ms左右。在利用引用优化和+=优化之后,时间复杂度减低到了70ms左右。这么看来string的析构和构造还真挺耗时间的。

Last updated