DeepSeek LeetCode 2019.解出数学表达式的学生分数 Go实现
以下是用 Go 实现的 LeetCode 2019 解法,使用区间 DP 枚举所有可能的运算顺序,再根据标准优先级计算正确结果来打分。
```go
func scoreOfStudents(s string, answers []int) int {
n := len(s)
// dp[i][j] 存储子表达式 s[i..j] 所有可能的结果
dp := make([][]map[int]bool, n)
for i := range dp {
dp[i] = make([]map[int]bool, n)
for j := range dp[i] {
dp[i][j] = make(map[int]bool)
}
}
// 1. 初始化单个数字
for i := 0; i < n; i += 2 {
dp[i][i][int(s[i]-'0')] = true
}
// 2. 区间 DP:长度从 3 开始,每次+2(保证子表达式合法)
for length := 3; length <= n; length += 2 {
for i := 0; i+length-1 < n; i += 2 {DeepSeek
j := i + length - 1
// 枚举运算符位置 k(奇数索引)
for k := i + 1; k < j; k += 2 {
// 左子表达式 s[i..k-1] ,右子表达式 s[k+1..j]
for left := range dp[i][k-1] {
for right := range dp[k+1][j] {
var res int
if s[k] == '+' {
res = left + right
} else { // '*'
res = left * right
}
if res >= 0 && res <= 1000 {
dp[i][j][res] = true
}
}
}
}
}
}
// 3. 标准正确结果(先乘后加)
correct := computeCorrect(s)
// 4. 统计分数
score := 0
allPossible := dp[0][n-1]
for _, ans := range answers {
if ans == correct {
score += 5
} else if allPossible[ans] {
score += 2
}
}
return score
}
// 计算按照标准优先级(* 大于 +)的表达式值
func computeCorrect(s string) int {
stack := []int{}
// 默认上一次的运算符为 '+',这样第一个数字直接入栈
var op byte = '+'
for i := 0; i < len(s); i++ {
if i%2 == 0 { // 数字位
num := int(s[i] - '0')
if op == '*' {
// 与栈顶相乘后放回
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
stack = append(stack, top*num)
} else {
stack = append(stack, num)
}
} else { // 运算符位
op = s[i]
}
}
sum := 0
for _, v := range stack {
sum += v
}
return sum
}
```
核心思路
· 表达式仅由个位数字和 '+'、'*' 组成,长度 n 必为奇数。
· 使用 dp[i][j] 记录子串 s[i..j] 通过任意加括号能得到的所有结果(范围 0~1000)。
· 按长度递增合并,枚举中间运算符,组合左右可能的结果。
· 标准结果单独用栈计算:遇 * 先乘,最后所有数相加。
· 评分:正确答案 +5 分,其他可能的运算结果 +2 分。
复杂度
· 时间:O(n³ × M²),其中 M 是可能结果数量(≤1001),实际远小于这个上界。
· 空间:O(n² × M),用于存储 DP 集合。
更多推荐



所有评论(0)