leetcode 241 Different Ways to Add Parentheses,分治,递归,二叉树,转换思路

先给出创新解法,再分析解法的本质,给出优化的代码。注意编码规范,注意函数入口和边界的处理。

 

引入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;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值