leetcode打卡--282. 给表达式添加运算符【关于回溯的模拟题】

题目

题目描述

给定一个仅包含数字 0-9 的字符串 num 和一个目标值整数 target ,在 num 的数字之间添加 二元 运算符(不是一元)+、- 或 * ,返回所有能够得到目标值的表达式。

示例1:

示例2:

示例3:

示例4:

示例5:

题目解析

题目描述很简单,就是给出一个字符串,和一个需要的值,给字符串固定位置添加运算符得出表达式,如果表达式的结果是给出的值,就加入答案,要求出所有这样的字符串。

我们很快想到用回溯的方式,每一层枚举计算的式子的每一项,然后最终得出答案。

回溯过程的处理我们需要注意以下两点的处理技巧:

  1. 对符号的添加处理,我们需要在需要添加符号的情况先预留一个空间给它用于添加符号(所以除了开始的表达式前没有符号
  2. 对乘号的处理,我们需要为添加乘号的时候进行特殊处理,因为乘号在这三个当中是最高的优先级,而且每次乘法不能直接与之前得到的结果相乘,需要与前一项相乘,如果前一项进行了 ‘+’ 或者 '-' 则直接取前一项的值进行相乘,(- 的时候需要为 -val),如果前一项是 * ,则需要把所有的相乘项作为一项来处理。我们把前一项记为 preVal 当前的值记为 res,此次需要处理的值记为 val,则 res = res - preVal + preVal*val
  3. 细节处理,这个包括对每一个单独项的提取,我们需要把0进行单独项处理,不能有前导0。
  • 如果还是看不懂,结合代码进行思考应该就懂了。

解题代码

class Solution {
public:
    vector<string> addOperators(string num, int target) {
        vector<string>ans;
        int n = num.size();
        //通过回溯得出答案,最主要的就是堆'*'号的处理:如果选择乘号,则前面的一项+或者-的值就要被消除,然后重新被乘起来得出答案。
        function<void(string&, int, long, long)> dfs = [&](string & exp, int i, long res, long preVal) {
            if (i == n) {
                if (res == target)
                    ans.push_back(exp);
                return;
            }
            int start = exp.size();
            if (start != 0) { //如果为第一次的选择,则不需要提前补位进行符号的选取
                exp.push_back('0');
            }
            long val = 0;
            //此处的附加判断用于防止前导0的表达式出现
            for (int j = i; j < n && (j == i || num[i] != '0'); j++) {
                val = val * 10 + num[j] - '0';
                exp.push_back(num[j]);
                if (start == 0) //如果首次则不需要选择符号
                    dfs(exp, j + 1, val, val);
                else {
                    exp[start] = '+'; dfs(exp, j + 1, res + val, val);
                    exp[start] = '-'; dfs(exp, j + 1, res - val, -val);
                    exp[start] = '*'; dfs(exp, j + 1, res - preVal + preVal * val, val * preVal);
                }
            }
            //通过resize进行回溯
            exp.resize(start);
        };
        string exp;
        dfs(exp, 0, 0, 0);
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值