分治

分治相关的题目如下:

序号 题目 难度
1 241. 为运算表达式设计优先级 中等

应用

1. Leetcode 241. 为运算表达式设计优先级

1.1. 题目

241. 为运算表达式设计优先级

给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。
生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 \(10^4\)

示例 1:

输入:expression = "2*3-4*5"
输出:[-34,-14,-10,-10,10]
解释:
\((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\)

1.2. 分析

我们利用分治的思想,以表达式中的运算符作为分割符,将原始的运算符分割成子表达式和运算符

我们定义一个递归函数:List<Integer> calculate(String expression) ,用于计算一个表达式的所有可能得计算结果。

通过递归的方式,直到将每一个子表达式分割成一个数字为止,然后,再根据对应的运算符,使用后序遍历,依次合并操作数的计算结果,最终即可得到运算的结果。

这里,由于需要枚举所有的可能优先级组合,因此,我们回溯的时候,需要枚举表达式中的每一个运算符的位置,以它作为起点开始分割表达式。

例如,我们以用例 expression = "2*3-4*5" 为例,来介绍分治的过程:

  • 第一种情况:以第一个运算符 \(expression[1]\) 分割原始的表达式,得到三个子表达式即:2*3-4*5,分解的过程如下:

    image

  • 第二种情况:以第二个运算符 \(expression[3]\) 分割原始的表达式,得到三个子表达式即:2*3-4*5,分解的过程如下:

    image

  • 第三种情况:以第三个运算符 \(expression[5]\) 分割原始的表达式,得到三个子表达式即:2*3-4*5,分解的过程如下:

    image

1.3. 代码实现

class Solution {
    private static final Set<Character> OPERATORS = new HashSet<>();

    public List<Integer> diffWaysToCompute(String expression) {
        OPERATORS.add('+');
        OPERATORS.add('-');
        OPERATORS.add('*');

        return calculate(expression);
    }

    private List<Integer> calculate(String expression) {
        // 计算每条路径上,每个节点返回的结果
        List<Integer> result = new ArrayList<>();
        // 枚举表达式中的运算符
        for (int i = 0; i < expression.length(); i++) {
            // 如果当前字符不是运算符,则跳过
            if (!OPERATORS.contains(expression.charAt(i))) {
                continue;
            }
            // 分治:将原始的表达式按照运算符分割成两个子表达式,并记录子表达式的值
            List<Integer> prevNums = calculate(expression.substring(0, i));
            List<Integer> postNums = calculate(expression.substring(i + 1));
            // 后序遍历:枚举当前运算符,与前后两个子表达式的计算结果的组合
            for (Integer prevNum : prevNums) {
                for (Integer postNum : postNums) {
                    result.add(compute(prevNum, postNum, expression.charAt(i)));
                }
            }
        }

        // 如果表达式expression中没有包含运算符,就是一个纯数字,那么就直接返回该数字
        if (result.isEmpty()) {
            result.add(Integer.valueOf(expression));
        }
        return result;
    }

    private Integer compute(Integer a, Integer b, char operator) {
        if (operator == '+') {
            return a + b;
        } else if (operator ==  '-') {
            return a - b;
        } else if (operator == '*') {
            return a * b;
        } else {
            return null;
        }
    }
}
posted @ 2023-05-06 16:52  LARRY1024  阅读(7)  评论(0编辑  收藏  举报