LeetCode 241 - Different Ways to Add Parentheses
LeetCode 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]
我的解答
这道题也是在分治算法分类中找的,属于Medium难度。
划分括号这个问题很经典,我曾经在离散数学课中接触过。只是那时候问题是求(x~0~ x~1~ x~2~ … x~n~)有多少种划分括号的方式,思路是考虑最后一次运算符的位置。这个位置可以是第一个运算符和最后一个运算符中任何一个,因此我们要遍历一下所有运算符。对于每个运算符,我们再递归地求解这个运算符左边和右边式子的可能数量,二者相乘,即当前运算符位置所具有的总可能数。将所有运算符可能数相加,就可以得到原式具有的所有括号划分的可能。
这个问题其实算是卡特兰数的一个特例。
对于这里的问题,我们只需要对上述问题解答略作修改:将求解子式的可能数改成求解子式可能的结果的集合。
关于时间复杂度,如果假设有n个数字的输入,A(n)为结果的集合大小,T(n)为对应的操作数量,有:
A(n)=∑n−1i=1A(i)A(n−i)
T(n)=∑n−1i=1(T(i)+T(n−i)+A(i)A(n−i))
我不知道怎么证明这里的时间复杂度,如果有心人看到可以讨论一下。不过根据卡特兰数的通项公式 (2nn)/(n+1) ,T(n)至少不是多项式级的。
class Solution {
public:
vector<int> diffWaysToCompute_helper(string input)
{
vector<int>re;//返回结果
vector<int>operand;//数
vector<char>binop;//运算符
vector<int>binop_pos;//运算符所在原字符串的位置
int tmp=0;
for(int i=0;i<input.size();i++)
{
if(isdigit(input[i]))
{
tmp=tmp*10+(input[i]-'0');
}
else
{
operand.push_back(tmp);
tmp=0;
binop.push_back(input[i]);
binop_pos.push_back(i);
}
}
operand.push_back(tmp);
if(binop.size()==0)
{
return {operand[0]};
}
if(binop.size()==1)
{
if(binop[0]=='+')
{
return {operand[0]+operand[1]};
}
else if(binop[0]=='-')
{
return {operand[0]-operand[1]};
}
else
{
return {operand[0]*operand[1]};
}
}
for(int i=0;i<binop.size();i++)
{
auto left=diffWaysToCompute_helper(input.substr(0,binop_pos[i]));
auto right=diffWaysToCompute_helper(input.substr(binop_pos[i]+1,input.size()-binop_pos[i]-1));
for(auto l:left)
{
for(auto r:right)
{
if(binop[i]=='+')
{
re.push_back(l+r);
}
else if(binop[i]=='-')
{
re.push_back(l-r);
}
else
{
re.push_back(l*r);
}
}
}
}
return re;
}
vector<int> diffWaysToCompute(string input)
{
auto r=diffWaysToCompute_helper(input);
sort(r.begin(),r.end());
return r;
}
};