创见博客
算法题中如何用 Node.js 读取输入
七崽爱吃小饼干2026/08/30阅读 0

在算法题中,Node.js 程序通常需要一次性读取标准输入,再根据题目格式解析。相比在业务代码中逐次等待用户输入,在线评测更适合使用 fs.readFileSync(0, 'utf8'):写法短、速度快,也更容易处理多行数据。

1. 最常用的写法:按空白字符切分

当输入中的数据都是数字,并且空格和换行只用于分隔数据时,可以直接把整份输入拆成 token:

js
const fs = require('fs')

const input = fs.readFileSync(0, 'utf8').trim().split(/\s+/)
let index = 0

const n = Number(input[index++])
const nums = Array.from({ length: n }, () => Number(input[index++]))

console.log(nums.reduce((sum, num) => sum + num, 0))

例如输入:

text
5
1 2 3 4 5

输出为:

text
15

这里的 /\s+/ 可以同时匹配空格、换行和制表符,因此不必关心数据具体分布在哪一行。

2. 需要保留行结构时

如果题目中的字符串可能包含空格,或者每一行有独立含义,就应该先按行切分:

js
const fs = require('fs')

const lines = fs.readFileSync(0, 'utf8').trimEnd().split(/\r?\n/)
const n = Number(lines[0])
const text = lines[1]

console.log(n)
console.log(text)

使用 /\r?\n/ 可以兼容 Linux 的 \n 和 Windows 的 \r\n。

3. 一个完整示例

假设输入格式如下:

  • 第一行包含 N、M、P
  • 第二行包含 N 个整数
  • 第三行包含 M 个整数
  • 计算所有 min(a[i] + b[j], P) 的和

可以这样写:

js
const fs = require('fs')

const tokens = fs.readFileSync(0, 'utf8').trim().split(/\s+/)
let index = 0

const n = Number(tokens[index++])
const m = Number(tokens[index++])
const p = Number(tokens[index++])

const a = Array.from({ length: n }, () => Number(tokens[index++]))
const b = Array.from({ length: m }, () => Number(tokens[index++]))

let result = 0

for (let i = 0; i < n; i++) {
  for (let j = 0; j < m; j++) {
    result += Math.min(a[i] + b[j], p)
  }
}

console.log(result)

原始输入经过 split 后得到的都是字符串。一定要先用 Number 转换,否则:

js
'2' + '3' // '23',不是 5

这也是 Node.js 算法题中非常常见的错误。

4. 使用 readline

readline 适合希望逐行处理输入的场景:

js
const readline = require('readline')

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
})

const lines = []

rl.on('line', (line) => {
  lines.push(line)
})

rl.on('close', () => {
  const [n, m] = lines[0].split(/\s+/).map(Number)
  const a = lines[1].split(/\s+/).map(Number)
  const b = lines[2].split(/\s+/).map(Number)

  console.log({ n, m, a, b })
})

不过对于大多数在线评测题,一次性读取输入通常更简洁。因此,没有流式处理需求时,优先使用 fs.readFileSync(0, 'utf8') 即可。

5. 常见问题

输入末尾有换行怎么办?

通常可以先调用 trim(),再切分:

js
const tokens = input.trim().split(/\s+/)

但如果题目允许空字符串作为有效输入,就不要直接使用 trim(),而应根据题意处理。

为什么不要只写 split(' ')?

split(' ') 只能处理单个空格,遇到多个空格或换行时容易产生空字符串。算法题中更稳妥的写法是:

js
input.trim().split(/\s+/)

数值很大时怎么办?

JavaScript 的 Number 不能精确表示所有大整数。若数值可能超过 Number.MAX_SAFE_INTEGER,应使用 BigInt:

js
const value = BigInt(token)
console.log(value.toString())

注意,BigInt 不能直接与 Number 混合运算。

输出很多内容怎么办?

频繁调用 console.log 可能影响性能。可以先把结果放入数组,最后一次性输出:

js
const output = []

output.push('first result')
output.push('second result')

console.log(output.join('\n'))

总结

Node.js 算法题的输入处理可以记住两个模板:

js
// 按空白字符读取
const tokens = require('fs').readFileSync(0, 'utf8').trim().split(/\s+/)
js
// 按行读取
const lines = require('fs').readFileSync(0, 'utf8').trimEnd().split(/\r?\n/)

只要根据题目选择正确的解析方式,并记得把数字字符串转换为 Number 或 BigInt,就能覆盖绝大多数在线评测场景。

评论
0/100