Leetcode 241:为运算表达式设计优先级(超详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/84638112

给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 *

示例 1:

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

示例 2:

输入: "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

解题思路

这个问题非常简单,和之前问题Leetcode 96:不同的二叉搜索树(超详细的解法!!!)Leetcode 95:不同的二叉搜索树 II(超详细的解法!!!)类似。我们首先想到的解法是通过递归,我们可以这样思考。我们考虑操作符的位置 i i ,我们定义 f ( i n p u t ) f(input) 返回输入为input的所有结果,那么 i i 左边的结果就是 f ( i n p u t [ : i ] ) f(input[:i]) i i 右边的结果就是 f ( i n p u t [ i + 1 : ] ) f(input[i+1:]) ,此时我们以 i i 为考虑对象时的所有结果就是

left = self._diffWaysToCompute(input[0:i])
right = self._diffWaysToCompute(input[i+1:])
for l in left:
    for r in right:
        res.append(self._calc(l, input[i], r))

我们的 i i 的范围就是[1,len(input)),每次步长为2。如果你对这个过程有困惑的话,一定要阅读我说的那两篇文章。

我们就非常容易的得到下面的代码

class Solution:
    def diffWaysToCompute(self, input):
        """
        :type input: str
        :rtype: List[int]
        """
        return self._diffWaysToCompute(input)
        
    def _diffWaysToCompute(self, input):
        if len(input) == 1:
            return [int(input[0])]
        
        if len(input) == 3:#bug
            return [self._calc(int(input[0]), input[1], int(input[2]))]
        
        res = list()
        for i in range(1, len(input), 2):
            left = self._diffWaysToCompute(input[0:i])
            right = self._diffWaysToCompute(input[i+1:])
            for l in left:
                for r in right:
                    res.append(self._calc(l, input[i], r))
                    
        return res
        
    def _calc(self, a, op, b):
        return {
            '+': a + b,
            '-': a - b,
            '*': a * b
        }[op]

但是上面这个代码存在一个bug,在len(input==3)的时候。我们希望的结果是对于a op b这种输入做处理,但是实际上ab可能不是个位数。但是其实不止这一处存在问题,我们后面的基于步长为2也是有问题的,所以我们需要重新整理代码。

class Solution:
    def diffWaysToCompute(self, input):
        """
        :type input: str
        :rtype: List[int]
        """
        return self._diffWaysToCompute(input)
        
    def _diffWaysToCompute(self, input):
        if input.isdigit():
            return [int(input)]
        
        res = list()
        for i in range(1, len(input)):
            if input[i] in "+-*":
                left = self._diffWaysToCompute(input[0:i])
                right = self._diffWaysToCompute(input[i+1:])
                for l in left:
                    for r in right:
                        res.append(self._calc(l, input[i], r))
                    
        return res
        
    def _calc(self, a, op, b):
        return {
            '+': a + b,
            '-': a - b,
            '*': a * b
        }[op]

我们同样可以用记忆花搜索的方式优化上面的代码。

class Solution:
    def diffWaysToCompute(self, input):
        """
        :type input: str
        :rtype: List[int]
        """
        mem = dict()
        return self._diffWaysToCompute(input, mem)
        
    def _diffWaysToCompute(self, input, mem):
        if input.isdigit():
            return [int(input)]
        
        if input in mem:
            return mem[input]
        
        res = list()
        for i in range(1, len(input)):
            if input[i] in "+-*":
                left = self._diffWaysToCompute(input[0:i], mem)
                right = self._diffWaysToCompute(input[i+1:], mem)
                for l in left:
                    for r in right:                      
                        res.append(self._calc(l, input[i], r))
                    
        mem[input] = res
        return res
        
    def _calc(self, a, op, b):
        return {
            '+': a + b,
            '-': a - b,
            '*': a * b
        }[op]

一个非常hacker的写法

def diffWaysToCompute(self, input):
    return [a+b if c == '+' else a-b if c == '-' else a*b
            for i, c in enumerate(input) if c in '+-*'
            for a in self.diffWaysToCompute(input[:i])
            for b in self.diffWaysToCompute(input[i+1:])] or [int(input)]

这个代码accept了,但是如果input里面出现负数该怎么办?这也需要考虑。由此展开的话题就变得很复杂了,有时间的话再将这个坑补上。

扫描二维码关注公众号,回复: 4405299 查看本文章

reference:

https://leetcode.com/problems/different-ways-to-add-parentheses/discuss/66350/1-11-lines-Python-9-lines-C++

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/84638112