2021.10.16 - 123.给表达式添加运算符

258 篇文章 0 订阅

1. 题目

在这里插入图片描述

2. 思路

(1) 迭代

  • 自己写的,没通过测试用例。

(2) 回溯法

  • 官方答案。

3. 代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.addOperators("1000000009", 9));
    }
}

class Solution {
    private List<Map<String, Long>> map = new ArrayList<>();

    public List<String> addOperators(String num, int target) {
        map.add(new HashMap<String, Long>() {{
            put(String.valueOf(num.charAt(0)), Long.valueOf(String.valueOf(num.charAt(0))));
        }});
        for (int i = 1; i < num.length(); i++) {
            String ch = String.valueOf(num.charAt(i));
            long val = Long.valueOf(ch);
            Map<String, Long> pre = map.get(i - 1);
            Map<String, Long> cur = new HashMap<>();
            for (Map.Entry<String, Long> entry : pre.entrySet()) {
                String s = entry.getKey();
                long v = entry.getValue();
                String s1 = s + "+" + ch;
                long v1 = v + val;
                cur.put(s1, v1);
                String s2 = s + "-" + ch;
                long v2 = v - val;
                cur.put(s2, v2);
                String s3 = s + "*" + ch;
                long v3 = multiple(s3);
                cur.put(s3, v3);
                if (num.charAt(i - 1) != '0') {
                    String s4 = s + ch;
                    long v4 = Blank(s4);
                    cur.put(s4, v4);
                }
            }
            map.add(cur);
        }
        List<String> res = new ArrayList<>();
        for (Map.Entry<String, Long> entry : map.get(map.size() - 1).entrySet()) {
            if (entry.getValue() == target) {
                res.add(entry.getKey());
            }
        }
        return res;
    }

    private long multiple(String num) {
        int mid = num.length() - 1;
        while (mid >= 0) {
            if (num.charAt(mid) == '+' || num.charAt(mid) == '-') {
                break;
            }
            mid--;
        }
        int preDigitCount = 0;
        for (int i = 0; i < mid; i++) {
            if (Character.isDigit(num.charAt(i))) {
                preDigitCount++;
            }
        }
        long preRes = 0;
        if (preDigitCount > 0) {
            preRes = map.get(preDigitCount - 1).get(num.substring(0, mid));
        }
        long postRes = 1;
        String str = num.substring(mid + 1) + "*";
        int left = 0;
        int right = left;
        while (right < str.length()) {
            while (right < str.length() && Character.isDigit(str.charAt(right))) {
                right++;
            }
            if (left < right) {
                postRes *= Long.valueOf(str.substring(left, right));
            }
            left = right + 1;
            right = left;
        }
        if (mid >= 0) {
            if (num.charAt(mid) == '+') {
                return preRes + postRes;
            } else {
                return preRes - postRes;
            }
        } else {
            return postRes;
        }
    }

    private long Blank(String num) {
        int mid = num.length() - 1;
        while (mid >= 0) {
            if (!Character.isDigit(num.charAt(mid))) {
                break;
            }
            mid--;
        }
        int preDigitCount = 0;
        for (int i = 0; i < mid; i++) {
            if (Character.isDigit(num.charAt(i))) {
                preDigitCount++;
            }
        }
        long preRes = 0;
        if (preDigitCount > 0) {
            preRes = map.get(preDigitCount - 1).get(num.substring(0, mid));
        }
        long postRes = Long.valueOf(num.substring(mid + 1));
        if (num.charAt(mid + 1) == '0') {
            return preRes;
        }
        if (mid >= 0) {
            if (num.charAt(mid) == '+') {
                return preRes + postRes;
            } else if (num.charAt(mid) == '-') {
                return preRes - postRes;
            } else {
                return multiple(num);
            }
        } else {
            return postRes;
        }
    }
}

class Solution1 {
    private int n;
    private String num;
    private int target;
    private List<String> ans;

    public List<String> addOperators(String num, int target) {
        this.n = num.length();
        this.num = num;
        this.target = target;
        this.ans = new ArrayList<String>();
        StringBuffer expr = new StringBuffer();
        backtrack(expr, 0, 0, 0);
        return ans;
    }

    private void backtrack(StringBuffer expr, int i, long res, long mul) {
        if (i == n) {
            if (res == target) {
                ans.add(expr.toString());
            }
            return;
        }
        int signIndex = expr.length();
        if (i > 0) {
            expr.append(0); // 占位,下面填充符号
        }
        long val = 0;
        // 枚举截取的数字长度(取多少位),注意数字可以是单个 0 但不能有前导零
        for (int j = i; j < n && (j == i || num.charAt(i) != '0'); ++j) {
            val = val * 10 + num.charAt(j) - '0';
            expr.append(num.charAt(j));
            if (i == 0) { // 表达式开头不能添加符号
                backtrack(expr, j + 1, val, val);
            } else { // 枚举符号
                expr.setCharAt(signIndex, '+');
                backtrack(expr, j + 1, res + val, val);
                expr.setCharAt(signIndex, '-');
                backtrack(expr, j + 1, res - val, -val);
                expr.setCharAt(signIndex, '*');
                backtrack(expr, j + 1, res - mul + mul * val, mul * val);
            }
        }
        expr.setLength(signIndex);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值