Leetcode - Expression Add Operators

My code:

import java.util.List;

public class Solution {
    public List<String> addOperators(String num, int target) {
        List<String> ret = new ArrayList<String>();
        if (num == null || num.length() == 0) {
            return ret;
        }
        helper(num, "", target, 0, (long) 0, (long) 0, ret);
        return ret;
    }
    
    private void helper(String num, String path, int target, int pos, long record, long multi, List<String> ret) {
        if (pos == num.length()) {
            if (record == target) {
                ret.add(path);
            }
            return;
        }
        for (int i = pos; i < num.length(); i++) {
            if (i != pos && num.charAt(pos) == '0') {
                break;
            }
            long curr = Long.parseLong(num.substring(pos, i + 1));
            if (pos == 0) {
                helper(num, path + curr, target, i + 1, curr, curr, ret);
            }
            else {
                // add
                helper(num, path + "+" + curr, target, i + 1, record + curr, curr, ret);
                // minus
                helper(num, path + "-" + curr, target, i + 1, record - curr, -curr, ret);
                // multiply
                helper(num, path + "*" + curr, target, i + 1, record - multi + multi * curr, multi * curr, ret);
            }
        }
    }
}

reference:
https://discuss.leetcode.com/topic/24523/java-standard-backtrace-ac-solutoin-short-and-clear

这道题目并没有自己做出来。看了答案。
我当时是打算用 Divide and Conquer来做的,就像burst ballon一样。但是很来发现了一个问题我午饭解决。
符号优先级问题。
比如:
“232”, 8
我从index = 0 处切开。
可以拿到我想要的。
2 + 3 * 2 = 8
在 HashMap 中, “2+32″ -> 8
但是当我在 index = 1处切开,
2 + 3 * 2 = 10
其实这里我算的是:
(2 + 3) * 2
但是在这里,他的字符串统一表示是: “2+3
2”
所以 HashMap 被重写
“2+3*2” -> 10

然后这个结果就遗失了。

所以,Divide and Conquer 很难解决这个优先级的问题。
于是看了答案,发现 DFS做得比较好。

仍然拿上个例子,
“232”, 8

首先我如此
-> 2+”32″
-> (2+3)”2″
-> (2+3)+2
-> (2+3)-2
-> (2+3)2 -> (2+3-3)+32 -> 2+3*2

可以看到,用这种方式,可以很好的区别出优先级。
他其实就是存储一个变量叫做 multi
如果这一层做加法, multi = curr
如果这一层做减法, multi = -curr
如果这一层做乘法,那么我需要考虑上一层做的是什么运算
如果是加法,
record = record+pre
现在要让 pre * curr
那么,
首先, record – pre 拿到一开始的record
然后, record + pre * curr
-> record = record – pre + pre * curr
= record – multi + multi * curr

如果是减法,
record = record – pre
那么,
首先 record + pre 拿到一开始的record
然后 record – pre * curr
这里,pre = -multi,
所以,
-> record = record + pre – pre * curr
= record + (-multi) – (-multi) * curr
= record – multi + multi * curr
再把 multi * curr 作为下一层的multi 传入。

这是最重要的一个地方,解决了优先级的问题,很巧妙。

还有个注意的就是剪枝问题。

如果 i > pos 并且 num.charAt(pos) == ‘0’ 的话,就不用继续搜索了。

比如,
“0231”, 8
一开始, pos = 0, i = 0,
会搜索 “0” +-* “231”
这已经把 “231”搜索了一遍了,

之后, pos = 0, i = 1
“02” +-* “31” 完全没必要了,但运算量会很大,所以剪枝。

还有个注意的地方就是,通过字符串扫描出来的整数,都得拿long来接受,因为说不定数字就比 Integer.MAX_VALUE 还大了。

注意了这些地方后,这道题目就可以做出来了。

Anyway, Good luck, Richardo! — 09/17/2016

    原文作者:Richardo92
    原文地址: https://www.jianshu.com/p/c62b1c090c3c#comments
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞