LeetCode 的奇怪 Bug 记录

题目不重要,就是今天的每日一题,把数学计算转换成树然后求值即可。
题解满天飞,而且大思路有的情况下,动手画一画应该就行。

重点在于发现了 LeetCode 的一个奇怪的 Bug

在本地调试时,测了很多组奇怪的数据,全部通过了,但是在 LeetCode 上却被一个并不奇怪的数据卡掉了。
但是本地测又完全没有问题,所以尝试通过调试输出查看问题,最后发现了一个更奇葩的情况

添加一个无意义的输出,会导致结果正确

简单描述下就是,本地跑、Go 官方的在线环境跑,都没有问题;在 LeetCode 上跑,结果不对,但是加了一个fmt.Print(),结果却又对了。
而显然fmt.Print()在代码里毫无意义,不应该影响就结果

代码如下,可以在 LeetCode 在线环境里测试。

package main

import "fmt"

type OpTree interface {
	Calc() int
	Debug() string
}

type Number struct {
	num int
}

func NewNumber(num int) *Number {
	return &Number{
		num: num,
	}
}

func (t *Number) Calc() int {
	if t == nil {
		return 0
	}
	return t.num
}

func (t *Number) Debug() string {
	if t == nil {
		return ""
	}
	return fmt.Sprint(t.num)
}

type Operator struct {
	L      OpTree
	R      OpTree
	Op     byte
	tempOp byte
}

func (t *Operator) Calc() (res int) {
	if t == nil {
		return 0
	}

	var l, r int
	if t.L != nil {
		l = t.L.Calc()
	}
	if t.R != nil {
		r = t.R.Calc()
	}

	switch t.Op {
	case '+':
		res = l + r
	case '-':
		res = l - r
	case '*':
		res = l * r
	case '/':
		res = l / r
	default:
		res = l
	}
	// fmt.Printf("%d %c %d = %d\n", l, t.Op, r, res)
	return res
}

func (t *Operator) Debug() string {
	if t == nil {
		return ""
	}
	l := ""
	r := ""
	if t.L != nil {
		l = t.L.Debug()
	}
	if t.R != nil {
		r = t.R.Debug()
	}
	return fmt.Sprintf("(%s) %c (%s)", l, t.Op, r)
}

func (t *Operator) Insert(nt OpTree, op byte) *Operator {
	if t == nil {
		t = new(Operator)
	}
    
	// ???
	// fmt.Print()
	
    if t.L == nil {
		t.L = nt
		t.Op = op
		return t
	} else if t.R == nil {
		t.R = nt
		t.tempOp = op
		return t
	}
	// 两侧都已满
	root := &Operator{
		L:      t,
		R:      nt,
		Op:     t.tempOp,
		tempOp: op,
	}
	return root
}

func Parse(s string, start, n int) (root *Operator, idx int) {
	root = new(Operator)
	var temp *Operator = nil
	num := 0
	hasNum := false

	getLeft := func() (left OpTree) {
		if hasNum {
			left = NewNumber(num)
			num = 0
			hasNum = false
		}
		if temp != nil {
			if left != nil {
				temp = temp.Insert(left, '[')
			}
			left = temp
			temp = nil
		}
		return
	}

	defer func() {
		root = root.Insert(
			getLeft(),
			']',
		)
		// if root.R == nil {
		// 	root = root.L.(*Operator)
		// }
	}()

	for i := start; i < n; i++ {
		switch s[i] {
		case '(':
			temp, i = Parse(s, i+1, n)
		case ')':
			return root, i
		case '+', '-':
			root = root.Insert(
				getLeft(),
				s[i],
			)
		case '*', '/':
			temp = temp.Insert(
				getLeft(),
				s[i],
			)
		case ' ':
			continue
		default:
			// 数字
			hasNum = true
			num = num*10 + int(s[i]-'0')
		}
	}
	return root, n
}

func calculate(s string) int {
	n := len(s)
	root, _ := Parse(s, 0, n)
	fmt.Println(root.Debug())
	return root.Calc()
}

func main() {
	// fmt.Println(calculate("0"))
	// fmt.Println(calculate("(1+2)*3"))
	// fmt.Println(calculate("1+2+3*4*5+6+(7+8)*9+10"))
	fmt.Println(calculate("1*2*3"))
}

已反馈给官方 #14618 工单 Go 语言执行结果存在问题