go 的输入与输出

在 Go 语言算法竞赛或大数据处理中,fmt.Scanfmt.Println 由于使用反射导致性能较差,容易引发超时。实现高性能 I/O 的核心是利用缓冲机制:

1. 高性能输入 (Fast Input)

使用 bufio.NewScanner(os.Stdin) 替代标准输入函数。通过设置 Split(bufio.ScanWords),扫描器可以自动跳过空格和换行符,直接获取目标字符串。获取字符串后,使用 strconv.Atoi 将其转换为整数,这种方式比直接扫描更快。

2. 高性能输出 (Fast Output)

使用 bufio.NewWriter(os.Stdout) 构建带缓冲的输出流。在写入时,配合 fmt.Fprintfmt.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
}

关键要点总结:

  1. 输入优化bufio.NewScanner 配合 Split(bufio.ScanWords)fmt.Scan 快得多,因为它避免了频繁的系统调用和反射消耗。
  2. 输出优化bufio.NewWriter 会将数据先存入内存缓冲区,最后通过 Flush() 一次性写出。
  3. 类型转换:利用 strconv.Atoi 将读取到的文本直接转为整数。

这个模板足以应对大多数算法竞赛中的超时问题。接下来,你想了解如何在这个基础上实现一个优先队列(堆),还是看看如何用切片高效模拟双端队列(Deque)

一些总结

判断边界的语句应该先判断是否越界再访问数组

1
2
3
for left < right && nums[left] == nums[left-1] {  
	left++  
}

链表中,如果需要哨兵节点,则需要初始化,比如

1
ans := &ListNode{}