go 的输入与输出#
在 Go 语言算法竞赛或大数据处理中,fmt.Scan 和 fmt.Println 由于使用反射导致性能较差,容易引发超时。实现高性能 I/O 的核心是利用缓冲机制:
使用 bufio.NewScanner(os.Stdin) 替代标准输入函数。通过设置 Split(bufio.ScanWords),扫描器可以自动跳过空格和换行符,直接获取目标字符串。获取字符串后,使用 strconv.Atoi 将其转换为整数,这种方式比直接扫描更快。
2. 高性能输出 (Fast Output)#
使用 bufio.NewWriter(os.Stdout) 构建带缓冲的输出流。在写入时,配合 fmt.Fprint 或 fmt.Fprintln 将数据先存入缓冲区。必须注意:在程序结束前一定要调用 Flush() 方法,否则留在缓冲区的数据将无法写入文件或控制台。
这是一个结合了高性能输入输出(Fast I/O)与基础算法逻辑的完整 Go 语言模板:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
// 定义全局变量,以便在函数间共享
var (
in = bufio.NewScanner(os.Stdin)
out = bufio.NewWriter(os.Stdout)
)
func main() {
// 设置按“单词”分割输入,自动跳过空格和换行
in.Split(bufio.ScanWords)
// 必须延迟调用 Flush,否则缓冲区数据不会被写出
defer out.Flush()
// --- 算法逻辑开始 ---
n := nextInt() // 读取元素个数
nums := make([]int, 0, n)
for i := 0; i < n; i++ {
nums = append(nums, nextInt())
}
// 使用高性能 fmt.Fprintln 输出结果
fmt.Fprintln(out, "读取到的数组和为:", sum(nums))
}
// 高性能读取整数
func nextInt() int {
in.Scan()
x, _ := strconv.Atoi(in.Text())
return x
}
// 高性能读取字符串
func nextString() string {
in.Scan()
return in.Text()
}
func sum(nums []int) int {
res := 0
for _, v := range nums {
res += v
}
return res
}
|
关键要点总结:#
- 输入优化:
bufio.NewScanner 配合 Split(bufio.ScanWords) 比 fmt.Scan 快得多,因为它避免了频繁的系统调用和反射消耗。 - 输出优化:
bufio.NewWriter 会将数据先存入内存缓冲区,最后通过 Flush() 一次性写出。 - 类型转换:利用
strconv.Atoi 将读取到的文本直接转为整数。
这个模板足以应对大多数算法竞赛中的超时问题。接下来,你想了解如何在这个基础上实现一个优先队列(堆),还是看看如何用切片高效模拟双端队列(Deque)?
一些总结#
判断边界的语句应该先判断是否越界再访问数组
1
2
3
| for left < right && nums[left] == nums[left-1] {
left++
}
|
链表中,如果需要哨兵节点,则需要初始化,比如