Similar to LC772 Basic Calculator III

# Definition for a binary tree node.
# class Node(object):
#     def __init__(self, val=" ", left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def expTree(self, s: str) -> 'Node':
        """
        main idea: [two stacks] use two stack to store operators and vals seperately
        rules1: when encountering '+-', if top of op stack is '+-*/', we merge two nodes in nums stack using top op in ops stack 
        rules2: when encountering '*/', if we can't compute previous '+-' due to priority limit.  we can merge top two nodes off nums stack only when we see '*/' in ops stack 
        rules3: when encountering ')', we merge the nodes until top of ops stack is '('
        """
        ops,vals = [],[] # ops store +-*/ and () 
        def mock_compute():
            op = ops.pop()
            r  = vals.pop()
            l  = vals.pop()
            vals.append(Node(op,l,r))
        for c in s:
            if c.isdigit():
                vals.append(Node(val = c))
            elif c in ['-','+']:
                while ops and ops[-1] in ['+','-','*','/']: # note here is while not if 
                    mock_compute()
                ops.append(c)
            elif c in ['*','/']:
                while ops and ops[-1]  in ['*','/']: # note here is while not if 
                    mock_compute()
                ops.append(c)
            elif c == '(':
                ops.append(c)
            elif c ==')':
                while ops[-1] != '(':
                    mock_compute()
                ops.pop() # remove '('
        while ops:
            mock_compute()
        return vals[0]
 ############# shorter version                
class Solution:
    def expTree(self, s: str) -> 'Node':
        ops,vals = [],[]
        def mock_compute():
            op = ops.pop()
            r  = vals.pop()
            l  = vals.pop()
            vals.append(Node(op,l,r))
        # return True if priority(op1) >= priority(op2)  = >  op1 in [+-*/] or op2 in [+,-]
        def compare(op1,op2)->bool:
            if op1 in ['(',')']:
                return False
            return op1 in ['*','/'] or op2 in ['+','-']
            
            
        for c in s:
            if c.isdigit():
                vals.append(Node(val = c))
            elif c == '(':
                ops.append(c)
            elif c ==')':
                while ops[-1] != '(':
                    mock_compute()
                ops.pop()
            else: # c in [+-*/]
                while ops and compare(ops[-1],c):
                    mock_compute()
                ops.append(c)
                
        while ops:
            mock_compute()
        return vals[-1]