DFS+回溯专题9 - leetcode282. Expression Add Operators/301. Remove Invalid Parentheses - Hard

282. Expression Add Operators

题目描述

给定一个字符串(仅包含数字0-9)和一个目标值,请在数字之间添加二元运算符:’+’、’-’ 和 ‘*’,使得运算结果为目标值。

例子
Example 1:

Input: num = “123”, target = 6
Output: [“1+2+3”, “123”]

Example 2:

Input: num = “232”, target = 8
Output: [“23+2", "2+32”]

Example 3:

Input: num = “105”, target = 5
Output: [“1*0+5”,“10-5”]

Example 4:

Input: num = “00”, target = 0
Output: [“0+0”, “0-0”, “0*0”]

Example 5:

Input: num = “3456237490”, target = 9191
Output: []

思想
想到用DFS遍历所有可能情况。对于加减法直接计算即可,但对于 ‘*’ 要考虑优先级
举两个例子:
2+3*4 : 应该首先计算 2+3=5,所以是计算5-3+3*4
2+3*4*5: 应该首先计算2+3*4 = 14,所以是计算14 - 3*4 +3*4*5
可以看出:我们需要存储上一轮 ‘+’ 或 ‘-’ 后的值,比如例子1的3和例子2的3*4

[设置以下变量]
pos 记录当前位置,val 记录当前计算的值
pre 记录加减法后的值,仅仅为了考虑 * ——multiplyHelper
加法:val + cur cur
减法:val - cur -cur
乘法:val - pre + pre * cur pre * cur
解法

class Solution(object):
    def addOperators(self, num, target):
        """
        :type num: str
        :type target: int
        :rtype: List[str]
        """
        res = []
        self.dfs(num, target, '', res, 0, 0, 0)
        return res
    def dfs(self, num, target, path, res, pos, val, pre):
        # pre is a MultiplyHelper, which stores the values after the lastest "+/-"
        if pos == len(num) and val == target:
            res.append(path)
        for i in range(pos, len(num)):
            # Remove the preLeading-zero, e.g "003"
            if i > pos and num[pos] == '0':
                break
                
            curStr = num[pos:i+1]
            cur = int(curStr)
            
            if pos == 0:
                self.dfs(num, target, path + curStr, res, i + 1, val + cur, cur)
            else:
                self.dfs(num, target, path + '+' + curStr, res, i + 1, val + cur, cur)
                self.dfs(num, target, path + '-' + curStr, res, i + 1, val - cur, -cur)
                self.dfs(num, target, path + '*' + curStr, res, i + 1, val - pre + pre * cur, pre * cur)             

301. Remove Invalid Parentheses

题目描述

移除最少数量的无效括号,使输入字符串有效。注意:输入字符串除了包含括号,还可能包含字母。

例子
Example 1:

Input: “()())()”
Output: ["()()()", “(())()”]

Example 2:

Input: “(a)())()”
Output: ["(a)()()", “(a())()”]

Example 3:

Input: “)(”
Output: [""]

思想
两种解法
法1 - DFS
首先统计需要移除的左右括号总数,分别记为left、right;
为加快速度 - 定义变量prior记录左括号>右括号的数目
法2 - BFS
定义函数isValidParentheses判断当前字符串是否有效;
如果有效,则只判断当前层的结点(BFS的深度 - 当前移除的括号总数),所以设置一个Flag变量只判断当前层结点是否有效(不再进一步尝试remove)

解法1
DFS

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        # left/right is the parentheses which need to be removed
        left = right = prior = 0
        for ss in s:
            if ss == '(':
                left += 1
            elif ss == ')':
                if left:
                    left -= 1
                else:
                    right += 1
        res = set()
        self.dfs(s, left, right, prior, 0, '', res)
        return list(res)

    def dfs(self, s, left, right, prior, pos, path, res):
        if left < 0 or right < 0 or prior < 0:
            return
        if pos == len(s):
            if left == right == prior == 0:
                res.add(path)
            return
        
        if s[pos] == '(':
            self.dfs(s, left-1, right, prior, pos+1, path, res)    # remove
            self.dfs(s, left, right, prior+1, pos+1, path + s[pos], res)    # add
        elif s[pos] == ')':
            self.dfs(s, left, right-1, prior, pos+1, path, res)    # remove
            self.dfs(s, left, right, prior-1, pos+1, path + s[pos], res)    # add
        else:
            self.dfs(s, left, right, prior, pos+1, path + s[pos], res)    # add

解法2
BFS

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        queue = [s]
        res = []
        visited = set([s])
        Flag = False
        while queue:
            cur = queue.pop(0)
            if self.isValidParentheses(cur):
                res.append(cur)
                Flag = True
            elif not Flag:    # the minimum number: if Flag == True, stop
                for i in range(len(cur)):    # Try to remove '(' or')'
                    if cur[i] in '()':
                        node = cur[:i] + cur[i+1:]
                        if node not in visited:
                            queue.append(node)
                            visited.add(node)
        return res
        
    def isValidParentheses(self, s):
        cnt = 0
        for ss in s:
            if ss == '(':
                cnt += 1
            elif ss == ')':
                if cnt == 0:    # Mark
                    return False
                cnt -= 1
        return not cnt
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值