LeetCode 241-为运算表达式设置优先级

52 阅读3分钟

题目

给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。

生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 104 。

示例 1:

输入: expression = "2-1-1"
输出: [0,2]
解释:
((2-1)-1) = 0 
(2-(1-1)) = 2

示例 2:

输入: 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 <= expression.length <= 20
  • expression 由数字和算符 '+''-' 和 '*' 组成。
  • 输入表达式中的所有整数值在范围 [0, 99]

思路

解法一: 分治

解法思路🔗: 241. 为运算表达式设计优先级 - Python/Golang 分治算法

将式子从任一个符号分开,左边的组合 运算 右边的组合,就是这个符号所在的所有的解,然后遍历中间所有的符号,就是这道题的所有解。左 运算 右的组合,和归并排序有点类似,

分治三步走

  • 1、分解:按运算符分成左右两部分,分别求解
  • 2、解决:实现一个递归函数,输入算式,返回算式解式
  • 3、合并:根据运算符合并左右两部分的解,得到最终解

代码一: 分治

class Solution:
    def diffWaysToCompute(self, expression: str) -> List[int]:
        # 分治思想
        res = []
        for i, char in enumerate(expression):
            # 当char为("+", "-", "*")时,开始
            if char in ("+", "-", "*"):
                # 根据char的位置,区分为[...,i),(i+1,...]区间进行分解
                left = self.diffWaysToCompute(expression[:i])
                right = self.diffWaysToCompute(expression[i+1:])
                # 根据char字符进行结果的查找
                for l in left:
                    for r in right:
                        if char == "+":
                            res.append(l+r)
                        elif char == "-":
                            res.append(l-r)
                        else:
                            res.append(l*r)
        
        if len(res) == 0:
            x = 0
            for i in range(len(expression)):
                x = x * 10 + int(expression[i])
            res.append(x)

        return res

解法二: dfs深度优先

解法思路🔗: 241. 为运算表达式设计优先级 - 【宫水三叶】运用 DFS 爆搜所有方案

根据运算符将式子分为左右2部分,设计递归函数 dfs(l,r),根据i位置的符号区分为 [l,i-1]和[i+1,r],最终答案为 dfs(0,n-1),为搜索子串expression(l,r)的所有运算结果。

dfs的出口就是,当l,r的区间只剩所有数字,不包含运算符,计算出数字。

对任意区间 expression(l,r):通过枚举(l,r)范围内的所有运算符来进行搜索,对于任意expression[i]为运算符,第一层遍历左边的所有结果l1,第二层遍历右边所有结果l2,对l1和l2进行expression[i]运算,得到expression[i]在(l,r)上的所有值,最后遍历所有长度的所有expression[i]就得到最终结果。

代码二: dfs深度遍历

使用for循环判断头尾,注意python中range是左闭右开区间,所以在遍历时需要赋值r+1。

class Solution:
    def diffWaysToCompute(self, expression: str) -> List[int]:
        def dfs(l, r):
            res = []
            for i in range(l, r+1):
                if expression[i] >= '0' and expression[i] <= '9':
                    continue
                left = dfs(l, i-1)
                right = dfs(i+1, r)
                for l1 in left:
                    for r1 in right:
                        cur = 0
                        if expression[i] == "+":
                            cur = l1 + r1
                        elif expression[i] == "-":
                            cur = l1 - r1
                        else:
                            cur = l1 * r1
                        res.append(cur)
                
            if len(res) == 0:
                cur = 0
                for i in range(l, r+1):
                    cur = cur * 10 + int(expression[i])
                res.append(cur)
            return res

        return dfs(0, len(expression)-1)

代码三: dfs遍历代码二

只是将for循环用while循环代替,更容易理解。

class Solution:
    def diffWaysToCompute(self, expression: str) -> List[int]:
        def dfs(l, r):
            res = []
            i = l
            while i <= r:
                if expression[i] >= '0' and expression[i] <= '9':
                    i += 1
                    continue
                left = dfs(l, i-1)
                right = dfs(i+1, r)
                for l1 in left:
                    for r1 in right:
                        cur = 0
                        if expression[i] == "+":
                            cur = l1 + r1
                        elif expression[i] == "-":
                            cur = l1 - r1
                        else:
                            cur = l1 * r1
                        res.append(cur)
                i += 1

            if len(res) == 0:
                j = l
                cur = 0
                while j <= r:
                    cur = cur * 10 + int(expression[j])
                    j += 1
                res.append(cur)
            return res
        
        return dfs(0, len(expression) - 1)