先给出创新解法,再分析解法的本质,给出优化的代码。注意编码规范,注意函数入口和边界的处理。
引入TreeNode,构造二叉树
定义为
TreeNode{
int val;
char op;
};
要么为运算符,要么为数字。
程序中约定op为' '时,val有效,该结点为数字结点,否则为运算符结点。
运算符结点的op为'+','-','*',为有效符号,对应的val无效,程序中约定为-1。
将添加括号的位置和顺序,转化成构造不同结构的二叉树,该二叉树的所有的叶子结点均为数字结点,非叶子结点为运算符结点。没有度为1的节点。
方案大体分三步:
1,解析input字符串里面所有的数字和运算符,List<Object> objList = parseIntOp(input);
2,构造满足约定规则的所有二叉树,List<TreeNode> trees = buildTree(objList);
3,计算每个二叉树,得到最终的结果集,return calcTrees(trees);
编码细节:
1,parseIntOp(input)中的input最好压缩掉字符间的所有空格,str = str.replaceAll(" ","");。
2,buildTrees和calcTrees均由相应递归函数buildTrees_recur和calcTrees_recur实现。注意recur函数中的递归出口。
3,buildTrees_recur中多处出现Object向基本类型转换的问题,
root = new TreeNode((Integer)objList.get(0),' ');
if(objList.get(i) instanceof Integer)continue;
tmpCh = (Character)objList.get(i);
4,所有函数入口处的参数检查,有些返回值并无意义,仅仅为了严谨。
class Solution {
class TreeNode{
int val;
char op;
TreeNode left = null, right = null;
public TreeNode(){
}
public TreeNode(int val, char op){
this.val = val;
this.op = op;
}
};
public List<Integer> diffWaysToCompute(String input) {
List<Integer> list = new ArrayList<Integer>();
if(input==null||input.length()==0)return list;
List<Object> objList = parseIntOp(input);
List<TreeNode> trees = buildTrees(objList);
return calcTrees(trees);
}
private List<Object> parseIntOp(String str){
List<Object> objList = new ArrayList<Object>();
if(str==null||str.length()==0)return objList;
str = str.replaceAll(" ","");
int tNum = 0;
for(int i = 0;i<str.length();++i){
if(Character.isDigit(str.charAt(i))){
tNum = tNum*10 + (str.charAt(i)-'0');
}else{
objList.add(tNum);
tNum = 0;
objList.add(str.charAt(i));
}
}
objList.add(tNum);
return objList;
}
private List<TreeNode> buildTrees(List<Object> objList){
List<TreeNode> trees = new ArrayList<TreeNode>();
if(objList==null||objList.size()==0)return trees;
return buildTrees_recur(objList);
}
private List<TreeNode> buildTrees_recur(List<Object> objList){
List<TreeNode> trees = new ArrayList<TreeNode>();
if(objList==null||objList.size()==0)return trees;
TreeNode root = null;
if(objList.size()==1){
root = new TreeNode((Integer)objList.get(0),' ');
trees.add(root);
return trees;
}
List<TreeNode> leftTrees = null, rightTrees = null;
Character tmpCh = null;
for(int i = 0;i<objList.size();++i){
if(objList.get(i) instanceof Integer)continue;
tmpCh = (Character)objList.get(i);
if(tmpCh=='+'||tmpCh=='-'||tmpCh=='*'){
leftTrees = buildTrees_recur(objList.subList(0,i));
rightTrees = buildTrees_recur(objList.subList(i+1,objList.size()));
for(int j = 0;j<leftTrees.size();++j){
for(int k = 0;k<rightTrees.size();++k){
root = new TreeNode(-1,tmpCh);
root.left = leftTrees.get(j);
root.right = rightTrees.get(k);
trees.add(root);
}
}
}
}
return trees;
}
private List<Integer> calcTrees(List<TreeNode> trees){
List<Integer> list = new ArrayList<Integer>();
if(trees==null||trees.size()==0)return list;
int res = -1;
for(int i = 0;i<trees.size();++i){
res = calcTrees_recur(trees.get(i));
list.add(res);
}
return list;
}
private int calcTrees_recur(TreeNode root){
if(root==null)return 0;
if(root.op==' ')return root.val;
int leftRes = calcTrees_recur(root.left);
int rightRes = calcTrees_recur(root.right);
int res = -1;
switch(root.op){
case '+':res = leftRes + rightRes;break;
case '-':res = leftRes - rightRes;break;
case '*':res = leftRes * rightRes;break;
}
return res;
}
}
还是分治的思路,代码主体仍是递归。
只是略去了解析input和构造并计算二叉树的过程,变成直接处理input字符串。
代码总量大幅度减少,总运行时间2ms,也比之前代码的效率高。
class Solution {
public List<Integer> diffWaysToCompute(String input) {
List<Integer> list = new ArrayList<Integer>();
if(input==null||input.length()==0)return list;
List<Integer> leftRes = null;
List<Integer> rightRes = null;
int res = -1;
for(int i = 0;i<input.length();++i){
if(Character.isDigit(input.charAt(i)))continue;
leftRes = diffWaysToCompute(input.substring(0,i));
rightRes = diffWaysToCompute(input.substring(i+1));
for(int j = 0;j<leftRes.size();++j){
for(int k = 0;k<rightRes.size();++k){
switch(input.charAt(i)){
case '+': res = leftRes.get(j) + rightRes.get(k);break;
case '-': res = leftRes.get(j) - rightRes.get(k);break;
case '*': res = leftRes.get(j) * rightRes.get(k);break;
}
list.add(res);
}
}
}
if(list.size()==0)list.add(Integer.parseInt(input));
return list;
}
}