Golang解决方案为何失败而Python却能通过?
Golang解决方案为何失败而Python却能通过? 我正在通过完成简单的编程挑战来自学Go语言。我在Python中解决的一个问题是这个:
https://codeforces.com/contest/463/problem/B
我通过所有测试的Python代码如下:
import math
import os
file = os.sys.stdin
n = int(file.readline().split(' ')[0])
heights = file.readline().split(' ')
heights.insert(0, 0)
cost = 0
energy = 0
for i, _ in enumerate(heights):
if i == 0:
continue
gain = int(heights[i - 1]) - int(heights[i])
energy += gain
if energy < 0:
cost += -energy
energy = 0
print(cost)
然而,当我将其翻译成Go语言时,我的解决方案失败了。我的Go语言解决方案:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
n, err := strconv.Atoi(scanner.Text())
check(err)
scanner.Scan()
heights := strings.Fields(scanner.Text())
heights = append([]string{"0"}, heights...)
cost := 0
energy := 0
for i := 1; i <= n; i ++ {
a, err := strconv.Atoi((heights[i - 1]))
check(err)
b, err := strconv.Atoi((heights[i]))
check(err)
gain := a - b
energy += gain
if energy < 0 {
cost += -energy
energy = 0
}
}
fmt.Println(cost)
}
func check(err error) {
if err != nil {
fmt.Println(err)
panic(err)
}
}
原因是它在测试9上失败了。以下是错误信息:

现在看起来字符串转换出了点问题。我已经阅读了文档,但无法弄清楚是怎么回事。有人能指导我一下这可能是什么问题吗?
除了strings.Split(),我还使用了strings.Fields()函数,但也失败了。
谢谢!
更多关于Golang解决方案为何失败而Python却能通过?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你的程序需要一个来自标准输入(例如命令行)的参数。如果没有提供任何有效值,第16行将会报错。
更多关于Golang解决方案为何失败而Python却能通过?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
感谢 @geosoft1,
我现在可以看到问题出在第16行。但我仍然不确定具体发生了什么,因为Codeforces服务器应该提供输入,正如错误消息附带的图片所示。
对于失败的测试用例,第一行应该是100000,第二行是一串数字。
有没有什么原因导致Codeforces服务器在运行程序时没有读取到100000这个输入?我是不是在什么地方犯了错误?
编辑:我找到原因了——我使用的是Mac系统,换行符是‘\n’,而服务器使用的是回车换行‘\r\n’作为换行符。切换到Windows风格的换行符后问题就解决了。
你的Go代码失败是因为输入处理逻辑有问题。问题出在读取n的方式上。
在Python代码中,你只读取了第一个数字:
n = int(file.readline().split(' ')[0])
但在Go代码中,你读取了整个第一行并尝试转换为整数:
scanner.Scan()
n, err := strconv.Atoi(scanner.Text()) // 如果第一行有多个数字,这会失败
实际上,Codeforces的输入格式是第一行只有一个整数n,但你的代码假设第一行可能有多个数字。然而问题463B的输入格式确实是第一行只有一个整数n,所以这里应该没问题。
真正的问题在于你的循环条件。在Python中,你遍历的是heights列表:
for i, _ in enumerate(heights):
if i == 0:
continue
# 处理逻辑
但在Go中,你只遍历到n:
for i := 1; i <= n; i ++ {
// 处理逻辑
}
这会导致如果heights的长度不等于n,你的循环就会出错。实际上,输入的第二行可能有n个高度值,但你的heights切片在开头插入了一个"0",所以长度变成了n+1。
正确的Go解决方案应该是:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
n, _ := strconv.Atoi(scanner.Text())
scanner.Scan()
heightsStr := strings.Fields(scanner.Text())
// 直接在切片前添加0,而不是创建新切片
heights := make([]int, n+1)
heights[0] = 0
for i := 1; i <= n; i++ {
h, _ := strconv.Atoi(heightsStr[i-1])
heights[i] = h
}
cost := 0
energy := 0
for i := 1; i <= n; i++ {
gain := heights[i-1] - heights[i]
energy += gain
if energy < 0 {
cost += -energy
energy = 0
}
}
fmt.Println(cost)
}
或者更简洁的版本:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
n, _ := strconv.Atoi(scanner.Text())
scanner.Scan()
heightsStr := strings.Fields(scanner.Text())
prev := 0
cost := 0
energy := 0
for i := 0; i < n; i++ {
h, _ := strconv.Atoi(heightsStr[i])
gain := prev - h
energy += gain
if energy < 0 {
cost += -energy
energy = 0
}
prev = h
}
fmt.Println(cost)
}
关键区别:
- 使用整数切片而不是字符串切片,避免重复转换
- 正确处理循环边界,确保处理所有高度值
- 简化逻辑,不需要在切片前插入"0",可以直接从0开始计算
这样应该能通过所有测试用例。

