​LeetCode刷题实战282:给表达式添加运算符

共 5096字,需浏览 11分钟

 ·

2021-06-02 20:37

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 给表达式添加运算符,我们先来看题面:
https://leetcode-cn.com/problems/expression-add-operators/

Given a string num that contains only digits and an integer target, return all possibilities to add the binary operators '+', '-', or '*' between the digits of num so that the resultant expression evaluates to the target value.

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

示例


示例 1:

输入: num = "123", target = 6
输出: ["1+2+3", "1*2*3"]

示例 2:

输入: num = "232", target = 8
输出: ["2*3+2", "2+3*2"]

示例 3:

输入: num = "105", target = 5
输出: ["1*0+5","10-5"]

示例 4:

输入: num = "00", target = 0
输出: ["0+0", "0-0", "0*0"]

示例 5:

输入: num = "3456237490", target = 9191
输出: []


解题

https://blog.csdn.net/RJ_theMag/article/details/108277129


对于每个位置的两个数之间,都有四种选择:加、减、乘、不填符号(这样两个数就连在一起构成一个更大的数)。

我们可以构造一个代数结构,使得不管下一个位置的数是什么,这个数后面填什么符号,我们都能记录前面已经计算过的字符串的值。

这个代数结构是a + b × c。a 是我们前面记录过的字符串表达式的值,b是我们当前搜索到的数,c是b下一个位置的数。

这样,如果c后面的符号是+,则整个表达式的值可以用(a+b×c) + 1 × _ 来维护,a + b × c就是a变量的下一个值,也就是我们当前已经搜索到的字符串表达式的值,_是剩下的字符串的值。a更新为 a+b×c, b更新为1;

同理,如果c后面的符号是-,则整个表达式的值可以用(a+b×c) + (-1) × _来维护。a更新为a+b×c, b更新为-1;
如果c后面的符号是×,则整个表达式的值可以用a+(b×c)×_来维护。a还是a,b更新为b×c。
如果c后面不填符号,我们直接更新c为一个更大的数: c = c × 10 + num[i] - ‘0’;表示两个数连起来成为一个数。

我们可以在字符串num的最后一位加上一个’+’,这样有一个好处,当我们搜索到倒数第二个位置(加上‘+’之前的最后一个位置)时,我们只要看a的值是否是target就行了,如果a的值是target,则我们可以存下来当前的方案path(path是一个string类型的变量)。 这是因为如果最后一位是‘+’,则当前的a被更新为a + b * c(上面分析过了),如果遍历完了原num字符串,这时的a就是最终的答案。


typedef long long LL; // 中间结果可能爆int,需要long long来存
class Solution {
public:
    vector<string> res;
    string path; // path存放当前方案

    void dfs(string& num, int u, int len, LL a, LL b, LL target) { // u是当前搜索到了字符串num的位置,len是当前方案path的长度
        if(u == num.size()) { // 如果搜索到了num的最后一个位置('+')
            if(a == target) { // 这时a存放的就是当前方案下字符串num的值
                res.push_back(path.substr(0, len - 1)); // len - 1是因为最后一位是'+'
            }
        } else {
            LL c = 0; // c是我们当前要搜索的数
            for(int i = u; i < num.size(); ++i) {
                c = c * 10 + num[i] - '0';
                path[len++] = num[i]; // 先把这个数加到方案path里
                path[len] = '+'; // 搜索'+'的方案
                dfs(num, i + 1, len + 1, a + b * c, 1, target); // a更新为a + b * c, b更新为1
                if(i + 1 < num.size()) { // 如果没到倒数第二位,说明还有插入'-'和'*'的方案
                    path[len] = '-';
                    dfs(num, i + 1, len + 1, a + b * c, -1, target); // a, b的更新之前已经分析过了
                    path[len] = '*';
                    dfs(num, i + 1, len + 1, a, b * c, target);
                }
                if(num[u] == '0') { // 不能有前导0
                    break;
                }
            }
        }
    }

    vector<string> addOperators(string num, int target) {
        path.resize(100); // 因为搜索的复杂度是指数级的,所以path长度不可能太长
        dfs(num, 0, 0, 0, 1, target); // 最开始a是0,b是1,表示 0 + 1 * (整个num表达式可能的取值)
        return res;
    }
};


好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。

上期推文:

LeetCode1-280题汇总,希望对你有点帮助!

LeetCode刷题实战281:锯齿迭代器


浏览 30
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报