边工作边刷题:70天一遍leetcode: day 63-1

Basic Calculator I/II

要点:这类题无论怎么变化,都有基本模式:两个stack,一个ops,一个oprand。遇到oprand就push,遇到ops要分情况。

  • ‘)’:括号里的结束。rewind or keep call computeAndPush
  • ‘(’:just push
  • ‘+-*/‘: 按优先级比较当前和ops.top(),while当前优先级低于ops.top()或者是'(',call computeAndPush
  • 当前优先级低于ops.top:三种可能:ops.top()是/,或者按从左到右顺序,或者’(’。所以反过来低优先级只有一种可能,当前为/而ops.top为+-

leetcode的两题稍微简单一点:I只有+-(),而II只有+-*/
I
错误点:

  • 什么时候push operand?如果等到下一个op,情况比较复杂,比如多个’)’会出错,所以计算数字的时候向前检查一个字符同时push
  • 字符串添加’+’:因为loop内只有在下一个op的时候计算ops栈顶运算,添加’+’可以不用loop外再处理
  • computeAndPush不用while loop,因为没有算符优先级,来一个算一个。
  • ‘)’最后出栈’('
class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        def computeAndPush(ops, oprands):
            op2 = oprands.pop()
            op1 = oprands.pop()
            op = ops.pop()
            if op=='+':
                oprands.append(op1+op2)
            else:
                oprands.append(op1-op2)
        
        num = 0
        ops = []
        oprands = []
        for i,ss in enumerate(s+'+'):
            if ss==' ': continue
            if ss.isdigit():
                num = num*10+ord(ss)-ord('0')
                if i+1==len(s) or not s[i+1].isdigit():
                    oprands.append(num)
                    num = 0
            else:
                if ss=='(':
                    ops.append('(')
                else:
                    if ss==')':
                        if ops and ops[-1]!='(': 
                            computeAndPush(ops, oprands)
                        ops.pop()
                    else:
                        if ops and ops[-1]!='(': computeAndPush(ops, oprands)
                        ops.append(ss)
            #print oprands
        #oprands.append(num)
        #if ops: computeAndPush(ops, oprands)
        return oprands[-1]
                    

II
错误点:

  • computeAndPush要用while loop,比如3+54-3:计算完后push-,ops中为[+,-]
  • hasPrecedence:ops栈中的运算符是要求高优先级的,要注意顺序
class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        def computeAndPush(ops, oprands):
            op2 = oprands.pop()
            op1 = oprands.pop()
            op = ops.pop()
            # print op1,op2,op
            if op=='+':
                oprands.append(op1+op2)
            elif op=='-':
                oprands.append(op1-op2)
            elif op=='*':
                oprands.append(op1*op2)
            elif op=='/':
                oprands.append(op1/op2)
        
        def hasPrecedence(op1, op2):
            if op1 in '*/' and op2 in '+-': return False
            return True

        oprands = []
        ops = []        
        num = 0
        for i,ss in enumerate(s+'+'):
            if ss==' ': continue
            if ss.isdigit():
                num=num*10+ord(ss)-ord('0')
                if i+1==len(s) or not s[i+1].isdigit():
                    oprands.append(num)
                    num=0
            else:
                while ops and hasPrecedence(ss, ops[-1]):
                    computeAndPush(ops, oprands)
                ops.append(ss)
            # print oprands
        return oprands[-1]
        
posted @ 2016-06-10 05:20  absolute100  阅读(166)  评论(0编辑  收藏  举报