241. Different Ways to Add Parentheses(divide and conquer)

来源:互联网 发布:淘宝店铺页头怎么换 编辑:程序博客网 时间:2024/06/17 13:29

()###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 *.

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) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
Output: [-34, -14, -10, -10, 10]

2. 算法分析

根据题意结合案例可知,对一个表达式进行计算,而且应该根据运算符op对表达式拆分,使得两边的表达式结合,进而在子表达式中按同样的规则再拆分、再结合,最后计算结果,求出用这种方式计算原表达式但所有结果。显然符合**分治-递归**的思想,而且很容易写出”divide”部分的代码,但对于每一个子问题的递归求借和子问题结果的合并则不是那么明朗。针对案例简单地画出**递归树**,可以发现有些子问题中的vector返回存在多于1个值,因此,需要采用嵌套循环处理子问题的结果(返回的vectors包含了两个子问题中即将参与op运算的所有值——组合问题)。

3. 算法设计

class Solution {public:vector<int> diffWaysToCompute(string input) {    vector<int> result;    char op;    int size = input.length();    for(int i = 0; i < size; i++) {        op = input[i];        if(op == '+' || op == '-' || op == '*') {            vector<int> result1 = diffWaysToCompute(input.substr(0, i));            vector<int> result2 = diffWaysToCompute(input.substr(i+1));            for(int n1 = 0; n1 < result1.size(); n1++) {                for(int n2 = 0; n2 < result2.size(); n2++) {                    int num1 = result1[n1];                    int num2 = result2[n2];                    if(op == '+') {                        result.push_back(num1 + num2);                    } else if(op == '-') {                        result.push_back(num1 - num2);                    } else {                        result.push_back(num1 * num2);                    }                                   }            }         }     }     /*最小单元,开始回溯*/     if(result.empty())        result.push_back(atoi(input.c_str()));      return result; }};

#### 3.1 运行测试

一直以来对递归的过程都把握的不太好,特别是回溯的过程,一开始在写下面这一嵌套循环的时候,误以为每一次回溯,result1和result2的长度都是1,所以一开始是这样的(默认vector只有一项):~~for(int n1 = 0; n1

                    int num1 = result1[0];                    int num2 = result2[0];                    if(op == '+') {                        result.push_back(num1 +num2);                    } else if(op == '-') {                        result.push_back(num1 - num2);                    } else {                        result.push_back(num1 * num2);                    }   

导致结果较小了。所以跟踪回溯,找出size>2的时候。如下图:
            for(int n1 = 0; n1 < result1.size(); n1++) {                for(int n2 = 0; n2 < result2.size(); n2++) {                    int num1 = result1[n1];                    int num2 = result2[n2];                    cout << "result1.size: " << result1.size()                          << " result2.size: " << result2.size() << endl;                    cout << num1 << op << num2 << " = ";                     ......

这里写图片描述

4. 算法优化

(待续)

阅读全文
0 0
原创粉丝点击