题目:
Basic Calculator的升级版,这次要求加括号了。
分析:
在Basic Calculator I里,做法是用stack存储整数,如果是乘除操作就先执行运算再存储,如果是加减的话就直接存储数据。这么做的实质其实是统一运算符的优先级——把优先级高的操作先执行掉,stack里存的数据都是优先级统一的加减操作,于是最后直接累加就可以了。
在这里也可以采取类似的思路,用stack来维护数据的运算顺序,但是需要先解决两个问题:
(1)如何给不同位置的运算符赋值?我们假设值越大的运算符优先级越高,比如说1+(2+34)-5这个表达式。初始的时候‘+’,‘-’的优先值是1, ‘’,‘/'的优先值是2,每一重左括号后的运算符优先值加3,每一个右括号后的优先值减3.因此上面表达式的四个运算符优先值是1,4,5,1。剩下的就是怎样找到一个数据结构,让优先级高的运算符两边的表达式先计算。(注意,这里是分支的策略,运算符两边的是表达式,不一定是数字)。
(2)另一个问题是如何利用运算符的优先值进行计算。很直观的想法是要不要按照优先值排序,最高的最早参与计算?这是不对的。比如说表达式:(0 +(1 + 2)) -(3 + (4 * 5 - (6 + 7)))
很明显,优先级最低的是中间的减号,把整个表达式分成了两个区间。这两个子区间之间的运算符需要按整体排序的顺序操作吗?肯定是不能这么做的。这里需要的不是整体有序,而是需要两个子区间内局部有序——在每个子区间里找到运算优先值最低的继续分治下去。所以这里就很适合用最小树(Cartersian tree)。
即一个序列里的最小值为根节点,最小值把序列分为左右两个子系列,分别为左子树和右子树,子树仍然是最小树。叶子节点是数字,非叶子节点是运算符。接下来就很直观啦,运算顺序就是树的postorder,每个运算符操作它的左右两个子树(对应的就是左右两个表达式)。
code:
import java.util.*;
class Solution{
static class TreeNode{
int val;
String s;
TreeNode left;
TreeNode right;
public TreeNode(int val, String s){
this.val = val;
this.s = s;
}
}
static int getPrioriyValue(String s, int base){
if(s.equals("+") || s.equals("-")) return base + 1;
else if(s.equals("*") || s.equals("/")) return base + 2;
else return Integer.MAX_VALUE;
}
static TreeNode BuildMinTree(String[] expression){
int val = 0;
int base = 0;
Stack<TreeNode> stack = new Stack<TreeNode>();
for(int i = 0; i < expression.length; i++){
if(expression[i].equals("(")){
base += 10;
continue;
}
if(expression[i].equals(")")){
base -= 10;
continue;
}
val = getPrioriyValue(expression[i], base);
TreeNode cur = new TreeNode(val, expression[i]);
//build tree O(n) time complexity
while(!stack.isEmpty() && cur.val <= stack.peek().val) cur.left = stack.pop();
if(!stack.isEmpty()) stack.peek().right = cur;
stack.push(cur);
}
TreeNode node = new TreeNode(0,"");
while(!stack.isEmpty()) node = stack.pop();
return node;
}
static ArrayList<String> reorder(String[] expression){
TreeNode node = BuildMinTree(expression);
ArrayList<String> list = new ArrayList<String>();
postOrder(node, list);
return list;
}
static void postOrder(TreeNode node, ArrayList<String> list){
if(node == null) return;
postOrder(node.left, list);
postOrder(node.right, list);
list.add(node.s);
}
static int calculate(ArrayList<String> list){
Stack<Integer> stack = new Stack<Integer>();
for(String s : list){
if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){
int op2 = stack.pop();
int op1 = stack.pop();
if(s.equals("+")) stack.push(op1 + op2);
if(s.equals("-")) stack.push(op1 - op2);
if(s.equals("*")) stack.push(op1 * op2);
if(s.equals("/")) stack.push(op1 / op2);
}
else stack.push(Integer.valueOf(s));
}
if(stack.isEmpty()) return 0;
else return stack.peek();
}
public static void main(String[] args){
String[] expression ={"3", "*", "6", "-", "(", "23", "+", "7", ")", "/", "(", "1", "+", "2", ")"} ;
ArrayList<String> list = reorder(expression);
for(String s : list) System.out.print(s + " ");
System.out.println("");
int result = calculate(list);
System.out.println(result);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。