分治算法(一)241Different Ways to Add Parentheses【middle】03-02

本文介绍了一种通过递归算法解析并计算数学表达式所有可能结果的方法。针对给定的算术表达式,算法能考虑所有可能的运算优先级组合,并返回所有可能的计算结果。

1、题目

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 *.


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]

题目大意:给定一个式子,求出所有按不同加括号的结果

2、分治体现

先看一个例子:2+1,不难发现,操作符左右两边分别是一个数,然后进行运算,因此, 无论运算式子多长都可以看成 A+B 这样的形式,A、B也可继续以同样的方式分下去
总之, 所有的操作都是相同的一种形式,因此本题可以递归求解,把操作符两边不断细分,直到操作符 left 和 right 只剩下一个数


3、解题思路

不同结果,说白了就是人为规定操作符运算次序导致的,【(*1)-(*2)】  , 【-(*1)(*2)】 。。。等,*1、*2是两个乘法。因此,解法思想归纳如下:

(1)得到操作符
(2)进入递归,得到操作符左右的数字,left 和 right
(3)left 和 right按照操作符进行运算

为了实现操作符不同次序的效果,可以遍历字符串,每得到一个操作符就进入递归,每次递归以该次遍历到的操作符划分左右

4、代码如下

class Solution {
public:

//to check wether the str is the original one [1]
    bool no(string str) {
	bool no1 = false;
	for (int i = 0; i < str.size(); i++)
		if (str[i] == '+' || str[i] == '-' || str[i] == '*')
			no1 = true;

	return no1;
}


//do the main job but get a vector out of order [2]
    vector<int> diffWaysToCompute2(string input) {
	vector<int> ret;
	for (int i = 0; i < input.size(); i++)
	{
		if (input[i] == '+' || input[i] == '-' || input[i] == '*')
		{
			vector<int> left = diffWaysToCompute2(input.substr(0, i));
			vector<int> right = diffWaysToCompute2(input.substr(i + 1, input.size()-i-1));
			
            //////////[3]
			for (int y = 0; y < left.size();y++) {
				for (int u = 0; u < right.size(); u++) {
					if (input[i] == '+')
						ret.push_back(left[y] + right[u]);
					else if (input[i] == '-')
						ret.push_back(left[y] - right[u]);
					else
						ret.push_back(left[y] * right[u]);
				}
			}
			
		}
	}
	

    ///////[4]
	if (input.size() >= 1 && !no(input)) {
		int te = 0;
		int allsize = input.size() - 1;

		for (int f = 0; f < input.size(); f++) {
			int gg = input[f] - '0';
			gg *= pow(10, allsize--);
			te += gg;
		}

		ret.push_back(te);
	}

	return ret;
}

//the right answer with a ordered vector [5]
    vector<int> diffWaysToCompute(string input) {
    
    vector<int> temp = diffWaysToCompute2(input);
	sort(temp.begin(), temp.end());

	return temp;
        
    }
};




对代码进一步说明:

注释【1】:这是为了递归基准备的,要结束递归的条件是:字符串只剩一个数字了,也就是  input.size() >= 1 && !no(input) :字符串size不小于一,且无操作符在其中(第一次提交被坑了,以为number只包括 0——9,显然不是)

注释【2】:没什么好说的

注释【3】:对应解题思路的步骤(3),但是为什么是一个嵌套循环呢?原先我写的是 left【0】+/-/* right【0】,后来发现结果少了几个,原因如下,举例 {2*3-4*5},当遍历这个字符串到 input【5】时,它最开始的 left 是 2*3-4,接下来遍历这个,会发现,由于包含两个操作符 *和-,根据不同顺序,得到的 left 会有两个值 2 和 -2,right同理

注释【4】:for 循环为了实现多位数从字符到int的转换

注释【5】:排序,用了sort 函数


最后,本文思路受以下博客启发,表示感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值