《前端笔试必备:JavaScript ACM输入输出模板》

引言:最近秋招黄金期,陆陆续续收到了一些笔试邀请,但很多都是ACM模式而不是力扣上的核心代码模式。所以代码题做起来无从下手,从网上找资料也很少有Javascript版本的ACM输入输出模板,并且也不够详细。于是自己搜集了许多资料,准备把常见的模板整理出来,希望可以帮到大家。

一、基础模板

我们先来看一个基础模板

js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 直接输出需要的字符串,不需要处理输入
    console.log("Hello Nowcoder!");
}()

我们接下来逐行解析下每行代码的作用

1. 引入 readline 模块并创建接口
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
  • require("readline"):引入Node.js内置的readline模块,这个模块用于从命令行(标准输入)读取一行一行的输入。
  • createInterface({ input: process.stdin }):创建一个输入接口,指定输入源为process.stdin(标准输入,也就是用户在控制台输入的内容)。
  • 变量rl就是这个输入接口的实例,后续通过它来控制输入的读取。
2. 创建异步迭代器
js 复制代码
var iter = rl[Symbol.asyncIterator]();
  • Symbol.asyncIterator是Javascript的一个内置符号,用于定义对象的异步迭代器
  • 这里通过rl[Symbol.asyncIterator]()获取rl接口的异步迭代器,赋值给iter
  • 异步迭代器的作用是:可以通过next()方法异步地获取下一行输入(因为输入是用户手动输入的,属于异步操作)。
3. 定义读取一行输入的函数
js 复制代码
const readline = async () => (await iter.next()).value;
  • 这是一个异步函数(async标记),作用是读取一行输入。
  • 调用iter.next()会返回一个Promise,await会等待这个Promise完成,获取下一行输入的结果。
  • 结果的value属性就是读取到的一行字符串(如果没有更多输入,value会是undefined)。
  • 简单说:调用readline()就可以得到一行输入的内容(字符串类型)
4. 立即执行的异步函数(核心逻辑区)
js 复制代码
void async function () {

      // Write your code here 👉 你的核心代码写在这里

      // 直接输出需要的字符串,不需要处理输入 console.log("Hello Nowcoder!"); 
}()

这是整个代码的执行入口,也就是你需要编写核心逻辑的地方,我们拆解一下:

  • void async function (){...}():这是一个立即执行的异步函数表达式 (IIFE)。
    • async标记:允许函数内部使用await关键字(因为读取输入输出是异步操作)。
    • void:避免函数执行后返回值可能导致的语法问题,单纯让函数执行。
    • 最后的():表示定义后立即执行这个函数。

核心代码写在哪里?

答案是:写在void async function () { ... }这个函数内部(也就是注释// Write your code here的位置)。根据题目的输入格式不同,你需要修改这个区域的代码。具体常见的输入格式见我第二部分详细讲解。

总结

这个模板的作用是标准化输入读取流程:

  1. 准备好读取输入的工具(rl接口,iter迭代器,readline函数)。
  2. 在立即执行的异步函数中,通过await readline()获取输入。
  3. 在函数内部编写你的核心逻辑(处理输入、计算、输出结果)。

二、常见出题形式

1.单组A+B

描述

给定两个整数ab,请你求出a + b的值。

输入描述:

第一行有两个整数ab

输出描述:

输入一个整数,代表a + b的值。

示例
js 复制代码
输入:
1 2
输出:
3
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // Write your code here
    while(line = await readline()){
        let tokens = line.split(' ');
        let a = parseInt(tokens[0]);
        let b = parseInt(tokens[1]);
        console.log(a + b);
    }
}()
核心逻辑解析

函数内部的while循环:

js 复制代码
while(line = await readline()) { ... }
  • 作用:持续读取每一行输入 ,直到没有更多输入(readline()返回undefined,循环终止)。
  • line = await readline():先调用readline()读取每一行输入,赋值给line
  • 当没有输入时,readline()先返回undefined,循环条件为false,退出循环。

循环内部的代码

js 复制代码
let tokens = line.split(' '); // 将一行输入按空格分割成数组(比如输入"1 2",得到["1", "2"]) 
let a = parseInt(tokens[0]); // 将第一个元素转为整数 
let b = parseInt(tokens[1]); // 将第二个元素转为整数 console.log(a + b); // 输出结果

2.多组_A+B_EOF形式

描述

给定若干组测试数据,读取至文件末尾为止,每组数据有两个整数a和b,请你求出a + b的值。

输入描述

每行有两个整数a和b,读取至文件末尾为止

输出描述

输出若干行,每行一个整数,代表a + b的值。

示例
js 复制代码
输入:
1 2
114 514
2024 727
输出:
3
628
2751
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 循环读取每一行输入,直到没有更多输入(EOF)
    while(line = await readline()){
        // 将一行输入按空格分割成数组(例如"1 2"分割为["1", "2"])
        let tokens = line.split(' ');
        // 将分割后的字符串转为整数
        let a = parseInt(tokens[0]);
        let b = parseInt(tokens[1]);
        // 输出两数之和
        console.log(a + b);
    }
}()

3.多组_A+B_T组形式

描述

给定t组测试数据。每组数据有两个整数a和b,请你求出a + b的值。

输入描述

第一行有一个整数t,每行有两个整数a和b

输出描述

输出t行,每行一个整数,代表a + b的值。

示例
js 复制代码
输入:
3
1 2
114 514
2024 727
输出:
3
628
2751
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 第一步:读取第一行,获取测试用例数量T
    let T = parseInt(await readline());
    
    // 第二步:循环T次,处理每组数据
    for (let i = 0; i < T; i++) {
        // 读取一行输入
        let line = await readline();
        // 分割成两个数字
        let tokens = line.split(' ');
        let a = parseInt(tokens[0]);
        let b = parseInt(tokens[1]);
        // 输出结果
        console.log(a + b);
    }
}()

4.多组_A+B_零尾模式

描述

给定若干组测试数据,最后一组数据为0 0,作为输入的结尾。每组数据有两个整数a和b,请你求出a + b的值。

输入描述

每行有两个整数a和b,最后一组数据为0 0,作为输入的结尾。

输出描述

输出若干行,每行一个整数,代表a + b的值。

示例
js 复制代码
输入:
1 2
114 514
2024 727 
0 0
输出:
3
628 
2751
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 循环读取每一行输入
    while(line = await readline()){
        // 分割并转换为数字
        let tokens = line.split(' ');
        let a = parseInt(tokens[0]);
        let b = parseInt(tokens[1]);
        
        // 关键:判断是否为0 0,是则终止循环
        if (a === 0 && b === 0) {
            break; // 退出循环,不再处理后续输入
        }
        
        // 不是终止条件则输出结果
        console.log(a + b);
    }
}()

5.单组_一维数组

示例
js 复制代码
输入:
3
1 4 7
输出:
12
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 第一步:读取第一行,获取数字的个数n
    let n = parseInt(await readline());
    
    // 第二步:读取第二行,获取包含n个数字的字符串
    let line = await readline();
    
    // 第三步:对字符串进行处理,转化为数字数组
    let nums = line.split(" ").filter(x => x).map(Number); // 用空格分割,过滤空值
    
    // 第四步:计算数组中所有数字的总和
    let sum = nums.reduce((acc, curr) => acc + curr, 0);
    
    // 第五步:输出总和
    console.log(sum);
}()

6.多组_一维数组_T组形式

示例
js 复制代码
输入:
3
3
1 4 7
1
1000
2
1 2
输出:
12
1000
3
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // 读取测试用例总数T
    const T = parseInt(await readline());

    // 循环处理每组数据
    for (let i = 0; i < T; i++) {
        // 读取当前组的元素个数n
        const n = parseInt(await readline());

        // 读取当前组的数组元素行
        const arrayLine = await readline();

        // 将字符串分割为数字数组
        const numbers = arrayLine.split(" ").filter(x => x).map(Number);

        // 计算数组总和(使用reduce累加,初始值为0)
        const sum = numbers.reduce((acc, current) => acc + current, 0);

        // 输出当前组的总和
        console.log(sum);
    }
})();

7.单组_二维数组

示例
js 复制代码
输入:
3 4
1 2 3 4
5 6 7 8
9 10 11 12
输出:
78
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 1. 读取第一行,获取二维数组的行数m和列数n
    let firstLine = await readline();
    let [m, n] = firstLine.split(' ').map(Number); // m=3, n=4(对应示例输入)
    
    let totalSum = 0; // 存储总和
    
    // 2. 循环读取m行数据(二维数组的每一行)
    for (let i = 0; i < m; i++) {
        let row = await readline(); // 读取一行数据(如"1 2 3 4")
        let nums = row.split(' ').filter(x => x).map(Number); // 转为数字数组(如[1,2,3,4])
        
        // 3. 累加当前行的所有元素到总和
        let rowSum = nums.reduce((acc, curr) => acc + curr, 0);
        totalSum += rowSum;
    }
    
    // 4. 输出二维数组所有元素的总和
    console.log(totalSum);
}()

8.多组_二维数组_T组形式

示例
js 复制代码
输入:
3
3 4
1 2 3 4
5 6 7 8
9 10 11 12
1 1
2024
3 2
1 1
4 5
1 4
输出:
78
2024
16
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // 1. 读取测试用例总数T
    const T = parseInt(await readline());

    // 2. 循环处理每组二维数组
    for (let t = 0; t < T; t++) {
        // 2.1 读取当前组的行数m和列数n
        const [m, n] = (await readline()).split(" ").filter(x => x).map(Number);

        let totalSum = 0; // 存储当前组的总和

        // 2.2 读取m行数据(二维数组的每一行)
        for (let i = 0; i < m; i++) {
            const row = (await readline()).split(" ").filter(x => x).map(Number);
            // 累加当前行的所有元素
            const rowSum = row.reduce((acc, curr) => acc + curr, 0);
            totalSum += rowSum;
        }

        // 2.3 输出当前组的总和
        console.log(totalSum);
    }
})();

9.单组_字符串

描述

给定一个长度为n的字符串s,请你将其倒置,然后输出。

输入描述

第一行有一个整数n,第二行有一个字符串s,仅包含小写英文字符。

输出描述

输出一个字符串,代表倒置后的字符串s

示例
js 复制代码
输入:
5
abcde
输出:
edcba
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 1. 读取第一行:字符串的长度n(本题中可忽略具体值,仅用于匹配输入格式)
    const n = parseInt(await readline());
    
    // 2. 读取第二行:需要反转的字符串
    const str = await readline();
    
    // 3. 反转字符串:
    //    - split('') 将字符串转为字符数组(如"abcde" → ['a','b','c','d','e'])
    //    - reverse() 反转数组(→ ['e','d','c','b','a'])
    //    - join('') 将数组转回字符串(→ "edcba")
    const reversedStr = str.split('').reverse().join('');
    
    // 4. 输出反转后的字符串
    console.log(reversedStr);
}()

10.多组_字符串_T组形式

描述

给定t组询问,每次只给出一个长度为n的字符串s,请你将其倒置,然后输出。

输入描述

第一行有一个整数t,随后t组数据。每组的第一行有一个整数n,每组的第二行有一个字符串s,仅包含小写英文字符。

输出描述

输出t行,每行一个字符串,代表倒置后的字符串s

示例
js 复制代码
输入:
3
5
abcde
8
redocwon
9
tfarcenim
输出:
edcba
nowcoder
minecraft
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // 1. 读取测试用例总数T
    const T = parseInt(await readline());

    // 2. 循环处理每组字符串
    for (let t = 0; t < T; t++) {
        // 2.1 读取当前组的字符串长度n(仅用于匹配输入格式,反转逻辑不依赖此值)
        const n = parseInt(await readline());

        // 2.2 读取当前组需要反转的字符串
        const str = await readline();

        // 2.3 反转字符串:拆分为字符数组 → 反转数组 → 拼接为字符串
        const reversedStr = str.split("").reverse().join("");

        // 2.4 输出反转后的字符串
        console.log(reversedStr);
    }
})();

11.单组_二维字符数组

输入描述

第一行有两个整数nm,随后n行,每行有m个字符,仅包含小写英文字符。

输出描述

输出一个二维字符数组。

示例
js 复制代码
输入:
3 4
abcd
efgh
ijkl
输出:
lkji
hgfe
dcba
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // 1. 读取第一行,获取二维数组的行数m和列数n
    const [m, n] = (await readline()).split(" ").filter(x => x).map(Number);

    // 2. 读取m行字符串,存储到数组中
    const rows = [];
    for (let i = 0; i < m; i++) {
        rows.push(await readline());
    }

    // 3. 处理逻辑:
    //    a. 先将每行字符串反转(如"abcd" → "dcba")
    //    b. 再将所有行的顺序反转(如[行1, 行2, 行3] → [行3, 行2, 行1])
    const reversedRows = rows
        .map((row) => row.split("").reverse().join("")) // 每行字符反转
        .reverse(); // 行顺序反转

    // 4. 逐行输出处理后的结果
    reversedRows.forEach((row) => console.log(row));
})();

12.多组_带空格的字符串_T组形式

描述

给定t组询问,每次给出一个长度为n的带空格的字符串s,请你去掉空格之后,将其倒置,然后输出。

输入描述

第一行有一个整数t,随后有t组数据。每组的第一行有一个整数n,每组的第二行有一个字符串s,仅包含小写英文字符和空格,保证字符串首尾都不是空格。

输出描述

输出t行,每行一个字符串,代表倒置后的字符串s

示例
js 复制代码
输入:
3
9
one space
11
two  spaces
14
three   spaces
输出:
ecapseno
secapsowt
secapseerht
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // 1. 读取测试用例总数T
    const T = parseInt(await readline());

    // 2. 循环处理每组字符串
    for (let t = 0; t < T; t++) {
        // 2.1 读取当前组的字符串总长度n(用于匹配输入格式)
        const n = parseInt(await readline());

        // 2.2 读取带空格的字符串
        const str = await readline();

        // 2.3 处理逻辑:
        //    a. 先将字符串所有字符(包括空格)反转
        //    b. 再去除反转后字符串中的所有空格
        const processed = str
            .split("") // 拆分为字符数组(含空格)
            .reverse() // 反转所有字符(包括空格)
            .join("") // 拼接回字符串
            .replace(/\s+/g, ""); // 去除所有空格(\s+匹配任意空白字符)

        // 2.4 输出处理结果
        console.log(processed);
    }
})();

13.单组_保留小数位数

描述

给定一个小数 n ,请你保留 3 位小数后输出。

如果原来的小数位数少于 3 ,需要补充 0 。

如果原来的小数位数多于 3 ,需要四舍五入到 3 位。

输出描述

输出一个小数,保留 3 位。

示例
js 复制代码
输入:
1.23
输出:
1.230

输入:
114.514
输出:
114.514

输入:
123
输出:
123.000
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 1. 读取输入的小数(单组输入,只需读一次)
    const numStr = await readline();
    
    // 2. 将字符串转换为浮点数
    const num = parseFloat(numStr);
    
    // 3. 保留3位小数:toFixed(3)会自动补零,确保结果是3位小数
    const result = num.toFixed(3);
    
    // 4. 输出格式化后的结果
    console.log(result);
}()

14.单组_补充前导零

描述

给定一个正整数 n ,请你保留 9 个数位,然后输出。

如果数位少于 9 个,那么需要补充前导零。

输出描述

输出一个小数,保留 3 位。

示例
js 复制代码
输入:
123
输出:
000000123

输入:
123456789
输出:
123456789
js 复制代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // 1. 读取输入的数字(单组输入,读取一行即可)
    const numStr = await readline();
    
    // 2. 补充前导零至9位:
    //    - padStart(9, '0') 表示如果字符串长度不足9位,在前面补'0'直到长度为9
    const result = numStr.padStart(9, '0');
    
    // 3. 输出处理后的结果
    console.log(result);
}()

三、总结

以上便是我们在笔试中经常会遇到的ACM输入输出题型,我们只需要特别牢记以下几点就可以很好得应对。

  • line = await readline():要注意await readline()获取的是一段字符串,后面我们还要自己将它分割或者转化为其他数据类型。
  • let tokens = line.split(' '):这段代码作用是,将一行输入按空格分割成数组(例如"1 2"分割为["1", "2"])。
  • let a = parseInt(tokens[0]):这段代码的作用是,将分割的字符转化为数字。

掌握以上这些,再配合whilefor语句就可以应对各种题型了。

相关推荐
前端鱼2 小时前
前端面试中值得关注的js题
前端·面试
UnnamedOrange2 小时前
有来前后端部署
前端·后端
力Mer2 小时前
全排列-遇到的深浅拷贝问题
javascript
德育处主任2 小时前
p5.js 绘制 3D 椭球体 ellipsoid
前端·javascript·数据可视化
未来之窗软件服务2 小时前
未来之窗昭和仙君 (四) 前端网页分页 — 东方仙盟筑基期
前端·仙盟创梦ide·东方仙盟·东方仙盟修仙·昭和仙君
安卓开发者2 小时前
鸿蒙Next Web组件详解:属性设置与事件处理实战
前端·华为·harmonyos
安卓开发者2 小时前
鸿蒙NEXT Web组件与JavaScript交互:打通原生与前端的桥梁
前端·javascript·harmonyos
fdc20173 小时前
Avalonia 基础导航实现:从页面切换到响应式交互全指南
开发语言·javascript·ecmascript
Sapphire~3 小时前
重学前端013 --- 响应式网页设计 CSS网格布局
前端·css