【Leetcode】282. Expression Add Operators

来源:互联网 发布:淘宝买单反靠谱吗 编辑:程序博客网 时间:2024/05/16 10:08

题目:https://leetcode.com/problems/expression-add-operators/?tab=Description

意思是给一个只包含数字的string,找出所有的可能的添加运算符+ - *的方式使得计算计算结果是target。

看了别人代码写的,里面有很多地方值得借鉴。

public List<String> addOperators(String num, int target) {List<String> r = new ArrayList<>();if(num == null || "".equals(num)) return r;addOperatorsSub(r, "", 0, num, target, 0, 0);return r;}public void addOperatorsSub(List<String> r, String path, int start, String num, int target, long sum, long pre_mul) {if(start >= num.length()){if(sum == target) r.add(path);return;}String backPart = ""; for(int i = start; i < num.length(); i++){ backPart += num.charAt(i); if(backPart.charAt(0) == '0' && backPart.length() > 1) break;   //1*05 long v = Long.parseLong(backPart); if(start == 0){ addOperatorsSub(r, path + backPart, i + 1, num, target, v, v); continue; }  addOperatorsSub(r, path + "+" + backPart, i + 1, num, target, sum + v, v); addOperatorsSub(r, path + "-" + backPart, i + 1, num, target, sum - v, -v); addOperatorsSub(r, path + "*" + backPart, i + 1, num, target, sum - pre_mul + pre_mul * v, pre_mul * v); }   }

大思路,使用的是backtracking,因为这里要返回所有解。

(1)之前有一道题目看上去类似,让返回加括号的方式,那个题目也是backtracking,不同的是那道题目需要用分治法,而这里却不用。为什么?原因是那道题把一个string分成两部分后,前一部分不可以看成一个基本的单元,而是也需要递归地去处理。因此前后两部分都需要递归。所以分治,可以说那道题目是一种比较特殊的处理方式。这里确实典型的backtrakcing处理,以第一个要处理的为单元,那么第一个可以是[0-1],[0-2],....,[0-n],前半部分可以看成基本单元,只需要对后面的部分递归处理就好。

(2)递归部分设计,递归定义的好坏直接决定这道题目的难度。这里有一个start,含义就是从num的第几位开始处理。那么函数中的[start, i]部分代表什么?很正常得会想到代表第一个操作数,那么后面的问题处理起来就比较复杂,因为如果是第一个操作数,那么附上操作符以后表达式的值算不出,没有第二个操作符。这样后续的递归很难处理。如果只有加法,处理起来没什么,有了减法,那么我处理完一步,往路径上附这一步的结果,path += (2 -),可以看到,这一步完成得不到目前为止的计算结过。显然不是一个好的定义方法。把[start,i]定义为第二个操作数就很好处理了。path+= (-3),这样就可以在之前的结果中计算出当前结果。

(3)处理乘法,乘法需要记录之前的乘积(如果之前有乘法),先减去之前的乘积,再加上新的乘积。如果之前乘法之前是一次减法,那么做完减法,应该传递当前值得负数给下面的函数。符号问题也可以处理。

(4)return case,这里的return case只看长度到最后的点,因为所有的字符都要用到,因此先看length,里面再看target == sum,写起来很简洁。如果不需要用全部的,那么length和target的检测要分开写。

0 0
原创粉丝点击