lintcode 271 · 前缀表达式转后缀表达式 【中等 栈 二叉树】

题目

https://www.lintcode.com/problem/271

将一个前缀表达式转换成后缀表达式。


输入的前缀表达式的字符串长度为 l,满足 

1≤l≤10 ^4
 
表达式中只包括四种符号 ‘+’,‘-’,‘*’,‘/’。

每个符号和变量之间用一个空格隔开。

样例中的中缀表达式是 "a - (b + c)"。

样例
输入:
str = "- a + b c"
输出:
"a b c + -"

思路

本题考查的是前缀表达式后缀表达式和表达式树的关系。

    表达式树所有的叶节点都是变量,非叶节点就是符号,连接两个子节点,
    它将获取子节点并且进行运算。
    表达式树的中序遍历就是我们常见的中缀表达式。
    前缀表达式就是表达式树的前序遍历,
    后缀表达式就是表达式树的后序遍历。
    本题需要将前缀表达式转换成表达式树的形式,
    并且进行后序遍历就可以得到后缀表达式。


    代码思路
    前缀表达式转换成表达式树:
    维护一个树节点的栈,倒序遍历前缀表达式:
    如果是变量,直接将这个变量的节点压入栈中。
    如果是符号,取出栈顶的两个节点,分别作为左右子节点,并将这个节点压入栈中。
    最后栈中剩下的节点就是表达式树的根节点。

答案

public class Solution {
    /**
     * @param str: the prefix notation.
     * @return: return the postfix notation.
     */
    public String prefixNotationToPostfixNotation(String str) {
               /*
        本题考查的是前缀表达式后缀表达式和表达式树的关系。

        表达式树所有的叶节点都是变量,非叶节点就是符号,连接两个子节点,
        它将获取子节点并且进行运算。
        表达式树的中序遍历就是我们常见的中缀表达式。
        前缀表达式就是表达式树的前序遍历,
        后缀表达式就是表达式树的后序遍历。
        本题需要将前缀表达式转换成表达式树的形式,
        并且进行后序遍历就可以得到后缀表达式。


        代码思路
        前缀表达式转换成表达式树:
        维护一个树节点的栈,倒序遍历前缀表达式:
        如果是变量,直接将这个变量的节点压入栈中。
        如果是符号,取出栈顶的两个节点,分别作为左右子节点,并将这个节点压入栈中。
        最后栈中剩下的节点就是表达式树的根节点。
         */
        String[] tokens = str.split(" ");
        //建立表达式树
        Node expressTree = buildExpTree(tokens);
        //获得表达式树的后序遍历
        List<String> postOrder = new ArrayList<>();
        postTravel(expressTree,postOrder);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < postOrder.size(); i++) {
            if(i>0) sb.append(" ");

            sb.append(postOrder.get(i));
        }
      return sb.toString();
    }

    public static Node buildExpTree(String[] strs){
        Stack<Node> stack = new Stack<>();
        //倒序遍历前缀表达式树构造表达式树
        int n= strs.length;
        for (int i = n-1; i >=0 ; i--) {
            Node node = new Node(strs[i]);
            if(isOperation(strs[i])){
                //如果是操作符,取除栈中2个元素,作为当前节点的子节点
                node.left = stack.pop();
                node.right = stack.pop();
                //并将这个阶段压入栈中
                stack.add(node);
            }else{ //如果是变量,直接压入栈中
                stack.add(node);
            }
        }

        return stack.peek();
    }

    //判断是否是操作符
    public static boolean isOperation(String s){
        return "+-*/".indexOf(s) !=-1;
    }

    public static void postTravel(Node root,List<String> postOrder){
        if(root ==null)
            return;

        postTravel(root.left,postOrder);
        postTravel(root.right,postOrder);
        postOrder.add(root.data);
    }
    static class Node{
        String data;
        Node left,right;
        public Node(String d){
            data =d;
            left=right =null;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵长辉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值