150. 逆波兰表达式求值-M-stack
根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入: [“2”, “1”, “+”, “3”, “*”]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:
输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: (4 + (13 / 5)) = 6
示例 3:
输入: [“10”, “6”, “9”, “3”, “+”, “-11”, “", “/”, "”, “17”, “+”, “5”, “+”]
输出: 22
解释:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
逆波兰式,用退栈的方式,很好解决;但有clean code hand book上的扩展,提出,如何提高该题目的扩展性,即继续添加符号,但不用怎么修改代码;所想当到的扩展方法 通过map[op string][f func]的方式实现。并且代码也变得简介许多,见code2.
- code1
package main
import "fmt"
import "strconv"
type stack struct {
data []string
}
func (s *stack) push(d string) {
s.data = append(s.data[:], d)
}
func (s *stack) pop() string {
if len(s.data) > 0 {
p := s.data[len(s.data)-1]
s.data = s.data[:len(s.data)-1]
return p
} else {
panic("null")
}
}
func(s*stack)show(){
fmt.Println(s.data)
}
func (s *stack) size() int {
return len(s.data)
}
func evalRPN(tokens []string) int {
var sk stack
for i := 0; i < len(tokens); i++ {
if tokens[i] == "+" {
if sk.size() >= 2 {
a,_ := strconv.Atoi(sk.pop())
b,_ := strconv.Atoi(sk.pop())
c:=a+b
sk.push(strconv.Itoa(c))
}
} else if tokens[i] == "/" {
if sk.size() >= 2 {
a,_ := strconv.Atoi(sk.pop())
b,_ := strconv.Atoi(sk.pop())
c:=b/a
sk.push(strconv.Itoa(c))
}
} else if tokens[i] == "*" {
if sk.size() >= 2 {
a,_ := strconv.Atoi(sk.pop())
b,_ := strconv.Atoi(sk.pop())
c:=b*a
sk.push(strconv.Itoa(c))
}
} else if tokens[i] == "-" {
if sk.size() >= 2 {
a,_ := strconv.Atoi(sk.pop())
b,_ := strconv.Atoi(sk.pop())
c:=b-a
sk.push(strconv.Itoa(c))
}
} else {
sk.push(tokens[i])
}
}
d,_:=strconv.Atoi(sk.pop())
return d
}
func main() {
fmt.Println(evalRPN([]string{"2", "1", "+", "3", "*"}))
fmt.Println(evalRPN([]string{"4", "13", "5", "/", "+"}))
fmt.Println(evalRPN([]string{"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"}))
}
- code2:扩展
package main
import "fmt"
import "strconv"
type stack struct {
data []string
}
func (s *stack) push(d string) {
s.data = append(s.data[:], d)
}
func (s *stack) pop() string {
if len(s.data) > 0 {
p := s.data[len(s.data)-1]
s.data = s.data[:len(s.data)-1]
return p
} else {
panic("null")
}
}
func (s *stack) size() int {
return len(s.data)
}
func fadd(a,b string)string{
ai,_ := strconv.Atoi(a)
bi,_ := strconv.Atoi(b)
c:=strconv.Itoa(bi+ai)
return c
}
func fsub(a,b string)string{
ai,_ := strconv.Atoi(a)
bi,_ := strconv.Atoi(b)
c:=strconv.Itoa(bi-ai)
return c
}
func fmult(a,b string)string{
ai,_ := strconv.Atoi(a)
bi,_ := strconv.Atoi(b)
c:=strconv.Itoa(bi*ai)
return c
}
func fdiv(a,b string)string{
ai,_ := strconv.Atoi(a)
bi,_ := strconv.Atoi(b)
c:=strconv.Itoa(bi/ai)
return c
}
var op map[string]func(a,b string)string
func init(){
op =make(map[string]func(a,b string)string)
op["+"]=fadd
op["-"]=fsub
op["*"]=fmult
op["/"]=fdiv
}
func evalRPN(tokens []string) int {
var sk stack
for i := 0; i < len(tokens); i++ {
if p,ok:=op[tokens[i]];ok {
if sk.size() >= 2 {
sk.push(p(sk.pop(),sk.pop()))
}
} else {
sk.push(tokens[i])
}
}
d,_:=strconv.Atoi(sk.pop())
return d
}
func main() {
fmt.Println(evalRPN([]string{"2", "1", "+", "3", "*"}))
fmt.Println(evalRPN([]string{"4", "13", "5", "/", "+"}))
fmt.Println(evalRPN([]string{"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"}))
}