【Lintcode】653. Expression Add Operators

题目地址:

https://www.lintcode.com/problem/expression-add-operators/description

给定一个只含数字的字符串 s s s,除了开头之外,其余位置可以插入加号、减号或者乘号成为一个合法的表达式。再给点一个数 t t t,要求返回所有算出来的值恰好等于 t t t的表达式。注意,每个数都不能有前导 0 0 0

思路是DFS。枚举每个位置截取数字,截取的时候注意不能有前导 0 0 0。如果在开头,则直接截取数字,然后进入下一层递归;如果不在开头,则不但要截取数字,而且还需要枚举进行三种不同的运算,由于有乘法运算的存在,它的优先级比加减法要高,所以要将做乘法的因子也要作为参数在递归的时候传递下去。例如,在枚举 a + b × c a+b\times c a+b×c的时候,要把 b × c b\times c b×c传递下去,这样在枚举乘法的时候,可以先将这个因子删掉,然后再加上这个因子乘以枚举的数,比如枚举了 d d d,那么就计算 a + ( b × c ) − ( b × c ) + ( b × c ) × d a+(b\times c)-(b\times c)+(b\times c)\times d a+(b×c)(b×c)+(b×c)×d,这样就能处理优先级的问题。代码如下:

import java.util.ArrayList;
import java.util.List;

public class Solution {
    /**
     * @param num:    a string contains only digits 0-9
     * @param target: An integer
     * @return: return all possibilities
     */
    public List<String> addOperators(String num, int target) {
        // write your code here
        List<String> res = new ArrayList<>();
        
        dfs(0, new StringBuilder(), 0, 0, num, target, res);
        return res;
    }
    
    private void dfs(int pos, StringBuilder sb, long cur, long last, String s, int target, List<String> res) {
    	// 如果枚举到了s的最后,则枚举完了,看一下算出来的结果是否是target
        if (pos == s.length()) {
            if (cur == target) {
                res.add(sb.toString());
            }
            
            return;
        }
        
        // 开始截取数字
        for (int i = pos; i < s.length(); i++) {
            String num = s.substring(pos, i + 1);
            // 如果有前导0则略过
            if (num.length() > 1 && num.charAt(0) == '0') {
                continue;
            }
            // 解析一下数字
            long curNum = Long.parseLong(num);
            // 按枚举的是不是第一个数字来分类
            if (pos == 0) {
            	// 如果是第一个数字,那么直接append,进入下一层递归
                sb.append(num);
                dfs(i + 1, sb, curNum, curNum, s, target, res);
                sb.setLength(sb.length() - num.length());
            } else {
            	// 如果不是第一个数字,就需要枚举三种运算
                sb.append('+').append(curNum);
                dfs(i + 1, sb, cur + curNum, curNum, s, target, res);
                // 回溯的时候恢复现场。注意,除了把运算符删掉之外,还需要把num本身的长度也给删掉
                sb.setLength(sb.length() - 1 - num.length());
                
                sb.append('-').append(curNum);
                dfs(i + 1, sb, cur - curNum, -curNum, s, target, res);
                sb.setLength(sb.length() - 1 - num.length());
                
                sb.append('*').append(curNum);
                dfs(i + 1, sb, cur - last + last * curNum, last * curNum, s, target, res);
                sb.setLength(sb.length() - 1 - num.length());
            }
        }
    }
}

时间复杂度是指数级,空间 O ( l s ) O(l_s) O(ls)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值