现在卡住的,其实不是“算法”,而是“输入模板的记忆方式”
本文最后更新于4 天前,其中的信息可能已经过时,如有错误请发送邮件到184874483@qq.com

这个非常正常,而且是初学者最常见的问题之一。

很多人不是不会做题,而是看到这种:

N, M = map(int, input().split())

A = []
for _ in range(N):
    A.append(list(map(int, input().split())))

脑子会断一下:
“这到底该怎么输入?”
“为什么要这么写?”
“我理解了,但下次还是记不住。”

你的问题不在于理解能力,而在于还没有把这种输入模式变成固定套路

所以这一节我们就不急着讲题,而是专门把这段输入模板彻底讲透,让你以后看到类似题目就能自己写出来。


先解决一个最根本的问题:到底“怎么输入”?

你说“我不知道如何把它进行输入”,这里其实有两种场景。

第一种:在刷题平台上提交代码

比如 HackerRank、LeetCode、牛客之类的平台。

这种情况下,你不用在代码里写死数据,平台会自动把测试数据一行一行喂给你的 input()

比如题目给的输入是:

2 3
1 2 3
4 5 6

那么程序执行时:

第一次 input() 读到的是:

"2 3"

第二次 input() 读到的是:

"1 2 3"

第三次 input() 读到的是:

"4 5 6"

也就是说,input() 每调用一次,就读一行。


第二种:你自己本地运行代码

如果你在本地运行,比如 VS Code、PyCharm、终端里跑 Python,那么程序运行到 input() 时,会停下来等你输入。

你就照题目样例,一行一行敲进去,比如:

2 3
1 2 3
4 5 6

每输完一行按一次回车。

所以你要记住一句非常关键的话:

input() 不是一次性把所有东西都读完,而是每次只读一整行。


先只记最核心的三句话

你现在先不要背整段代码,先只记这三句话:

第一句:input() 读一整行

比如输入:

2 3

那么:

input()

读到的是字符串:

"2 3"

注意,是字符串,不是数字。


第二句:.split() 按空格切开

input().split()

会把 "2 3" 变成:

["2", "3"]

它得到的是字符串列表


第三句:map(int, ...) 把每个字符串变成整数

map(int, ["2", "3"])

会把每一项分别转成整数,变成相当于:

2, 3

所以:

N, M = map(int, input().split())

整体意思就是:

读一行 → 按空格切开 → 每项转成整数 → 分别给 N 和 M。


单独拆开讲:N, M = map(int, input().split())

我们把它拆成最笨、最容易懂的写法。

原写法

N, M = map(int, input().split())

拆开后其实相当于

line = input()           # 读入一整行,比如 "2 3"
parts = line.split()     # 变成 ["2", "3"]
numbers = map(int, parts)  # 把 "2" 和 "3" 变成 2 和 3
N, M = numbers

如果再写得更适合初学者一点,可以想成:

line = input()
parts = line.split()

N = int(parts[0])
M = int(parts[1])

这两种写法本质是一回事。

所以你不是记不住它,而是你之前把它当成“一句神秘咒语”在记。
现在你要把它看成是 4 个小动作连在一起。


再拆第二段:为什么要这样读数组?

现在看这一段:

A = []
for _ in range(N):
    A.append(list(map(int, input().split())))

你可以先不要整体看,先看它在做什么。


第一步:先准备一个空列表

A = []

意思是:我先准备一个地方,用来装整个二维数组。

你可以把 A 想成一个“总盒子”。


第二步:循环 N 次

for _ in range(N):

意思是:数组 AN 行,所以我要读 N 次。

如果 N = 2,那就读两行。
如果 N = 3,那就读三行。

这里的 _ 只是表示“这个循环变量我不用”。

比如:

for _ in range(2):

就表示“做两次”。


第三步:每次读一行,并变成整数列表

list(map(int, input().split()))

比如这一行输入是:

1 2 3

那么它的变化过程是:

input()           -> "1 2 3"
input().split()   -> ["1", "2", "3"]
map(int, ...)     -> 1, 2, 3
list(...)         -> [1, 2, 3]

所以这一整句的作用就是:

把一行数字读成一个列表。


第四步:把这一行塞进 A 里面

A.append([1, 2, 3])

如果第一轮循环读到 [1, 2, 3],那 A 变成:

[[1, 2, 3]]

如果第二轮又读到 [4, 5, 6],那 A 变成:

[[1, 2, 3], [4, 5, 6]]

这就成了一个二维列表。


用一个完整例子手动模拟一遍

假设输入是:

2 3
1 2 3
4 5 6

现在一步一步来。


第 1 行输入

执行:

N, M = map(int, input().split())

读到:

"2 3"

切开后:

["2", "3"]

转整数后:

2, 3

所以:

N = 2
M = 3

初始化 A

A = []

现在:

A = []

第 1 次循环

执行:

A.append(list(map(int, input().split())))

读到第二行:

"1 2 3"

处理后变成:

[1, 2, 3]

追加后:

A = [[1, 2, 3]]

第 2 次循环

再执行一次:

A.append(list(map(int, input().split())))

读到第三行:

"4 5 6"

处理后变成:

[4, 5, 6]

追加后:

A = [[1, 2, 3], [4, 5, 6]]

到这里,二维数组就读完了。


你真正要记的,不是代码本身,而是“输入套路”

你现在不要死记这一长串代码,而是记下面这个套路。

模板 1:读一行多个整数

如果题目一行里有多个数字,比如:

2 3

你就用:

N, M = map(int, input().split())

你可以把它翻译成一句中文:

“读一行,用空格切开,转成整数,分别接住。”


模板 2:读 N 行数组

如果题目说“接下来有 N 行,每行若干个整数”,你就用:

A = []
for _ in range(N):
    row = list(map(int, input().split()))
    A.append(row)

翻译成中文就是:

“准备一个大列表,然后循环读 N 行,每行变成一个小列表,再塞进去。”


比起背代码,更推荐你记“句子版”

你以后写输入时,脑子里先默念这个:

N M

“先读第一行,拿到行数和列数。”

对应代码:

N, M = map(int, input().split())

读数组 A

“数组 A 有 N 行,所以循环 N 次;每次读一行整数,放进 A。”

对应代码:

A = []
for _ in range(N):
    row = list(map(int, input().split()))
    A.append(row)

你如果先能把这两句中文说出来,代码其实就比较容易跟着写出来。


为什么你会“理解,但记不住”?

因为你现在很可能是在记“长相”,不是记“动作”。

比如这句:

A.append(list(map(int, input().split())))

如果你把它当成一个整体去背,当然很难记。

但如果你把它拆成 4 个动作:

  1. 读一行
  2. 按空格切开
  3. 转成整数列表
  4. 追加到 A

那就容易多了。

所以以后不要背:

A.append(list(map(int, input().split())))

而是先想:

“我要读一行整数列表,然后放进 A。”

写不顺时,就拆开写:

row = list(map(int, input().split()))
A.append(row)

这比一口气写完整句更适合初学者。


初学者更推荐的写法

你完全可以先写成这种更清楚的版本:

N, M = map(int, input().split())

A = []
for _ in range(N):
    row = input().split()
    row = list(map(int, row))
    A.append(row)

这个版本虽然多写了几行,但逻辑更清楚。

等你熟了,再压缩成:

A.append(list(map(int, input().split())))

这才是正常学习路径。

不是一开始就非得写得很短。


给你一个真正适合记忆的“万能输入骨架”

以后你看到这种二维数组题,可以先默写这个:

N, M = map(int, input().split())

A = []
for _ in range(N):
    row = list(map(int, input().split()))
    A.append(row)

你就把它理解成:

  • 第一行:读规模
  • 后面循环:一行一行读数据

这已经够用了。

如果还有第二个数组 B,那就再来一遍:

B = []
for _ in range(N):
    row = list(map(int, input().split()))
    B.append(row)

一个更实用的记忆法:按题目类型记模板

你以后做输入题,可以只分这 3 类。

第一类:只输入一个数

例如:

5

写法:

n = int(input())

第二类:一行输入多个数

例如:

2 3

写法:

N, M = map(int, input().split())

或者如果不确定有几个数:

nums = list(map(int, input().split()))

第三类:输入一个二维数组

例如后面还有 N 行:

1 2 3
4 5 6

写法:

A = []
for _ in range(N):
    row = list(map(int, input().split()))
    A.append(row)

你以后只要先判断题目属于哪一类,模板就容易拿出来了。


本节最重要的结论

你现在真正要掌握的,不是“把代码背下来”,而是这两个核心认知:

第一,input()一行一行读
第二,二维数组的读取本质就是:循环读 N 行,每一行变成一个列表,再装进总列表。

只要这两点稳了,这类输入你就不会再特别怕。


你现在可以这样练,不要死背

建议你自己连续手写 3 遍下面这段,不看答案:

N, M = map(int, input().split())

A = []
for _ in range(N):
    row = list(map(int, input().split()))
    A.append(row)

每写一遍,都在旁边写中文解释:

  • 读第一行,得到 N 和 M
  • 建一个空列表 A
  • 循环 N 次
  • 每次读一行整数
  • 把这一行加进 A

这样记得比单纯背代码牢很多。


方法总结

以后看到这类输入,不要慌,按这个顺序想:

第一步:题目让我读几次?

  • 一次?
  • N 次?
  • 2N 次?

第二步:每次读的是一个数,还是一整行多个数?

  • 一个数:int(input())
  • 多个数:map(int, input().split())

第三步:最后我要存成什么?

  • 单个变量
  • 一维列表
  • 二维列表

只要这三问能答出来,输入模板基本就能自己拼出来。


练习

你先做一个最小练习,不要急着看答案。

练习题

输入如下:

3 2
1 2
3 4
5 6

请你把它读成:

  • N = 3
  • M = 2
  • A = [[1, 2], [3, 4], [5, 6]]

提示

你只需要写输入部分,不用做后续计算。
先自己试着写:

  1. 第一行读 N, M
  2. 建空列表 A
  3. 循环 N
  4. 每次读一行并追加到 A

不是不懂“为什么要这么做”,现在真正卡住的是:

  1. inputsplitmapintlist 这几个东西到底谁先谁后
  2. append() 到底是在哪一步加进去的
  3. 这一串组合一长,就容易乱

这一步其实已经比“完全不会”进步很多了。因为你现在不是不会,而是顺序感不稳
那这次我们就专门解决“顺序”问题。


先记一个最核心原则:看这种组合,要“从里往外”读

比如这句:

list(map(int, input().split()))

不要从左往右硬读。
这种嵌套结构,最稳的读法是:

先看最里面,再一层一层往外包。

就像剥洋葱一样。


把这句拆开:到底谁先执行?

我们来看:

list(map(int, input().split()))

执行顺序其实是这样的:

第 1 步:先执行 input()

input()

因为它在最里面。

作用:读入一整行字符串。

比如你输入:

1 2 3

那么:

input()

得到的是:

"1 2 3"

第 2 步:再执行 .split()

input().split()

作用:把这一整行按空格拆开。

所以:

"1 2 3".split()

得到:

["1", "2", "3"]

注意,这里还是字符串,不是整数。


第 3 步:再执行 map(int, ...)

map(int, input().split())

作用:把拆出来的每个字符串,逐个用 int() 转成整数。

也就是把:

["1", "2", "3"]

变成“相当于”:

1, 2, 3

这里你可以先把 map(int, ...) 暂时理解成:

“把里面的每一项都做一次 int 转换。”


第 4 步:最后执行 list(...)

list(map(int, input().split()))

作用:把前面那些转换好的整数,真正收集成一个列表。

所以最后结果就是:

[1, 2, 3]

所以这串组合的执行顺序是

不是你写出来的顺序,而是:

input() 
→ split() 
→ map(int, ...)
→ list(...)

你可以把它记成一句话:

先读,后切,再转,最后装。

这是最重要的一句记忆口诀。


给你一个特别适合记忆的顺口版

看到这句:

list(map(int, input().split()))

脑子里不要背代码,直接念中文:

读一行 → 切开 → 转整数 → 变列表

也就是:

  • input():读一行
  • .split():切开
  • map(int, ...):转整数
  • list(...):装成列表

你以后只要先会说这句中文,代码就容易写出来。


单独讲:为什么 int 写在 map 里面?

很多初学者会看到这里有点懵:

map(int, input().split())

会想:“为什么不是 int(map(...))?为什么不是 split(int)?”

这里你要记住:

map(函数, 数据) 的意思是

把“函数”作用到“数据里的每一项”上。

比如:

map(int, ["1", "2", "3"])

意思就是:

  • "1"int()
  • "2"int()
  • "3"int()

结果相当于得到:

1, 2, 3

所以:

  • int 是“处理规则”
  • input().split() 是“要处理的数据”

这就是为什么 int 要放在 map 的第一个位置。


再单独讲:append() 到底是在什么时候做的?

你现在第二个容易乱的地方,就是这个:

A.append(list(map(int, input().split())))

你会觉得:
“到底是先 append,还是先 input?”
append 在整个过程里是干嘛的?”

答案是:

先把右边整出来,再 append 到 A。


这句真正的顺序是这样

A.append(list(map(int, input().split())))

不要整体看,把它拆成两部分:

右边先算出来

list(map(int, input().split()))

这一部分先执行,最终会得到一个列表,比如:

[1, 2, 3]

然后再执行 append

有了这个结果后,才执行:

A.append([1, 2, 3])

也就是说:

append() 不是一边读一边加,它是等右边先准备好一个完整的小列表,再把这个小列表塞进 A


所以 append 可以这样记

append(x) 的意思不是“处理数据”

它只是:

把已经准备好的东西 x,加到列表最后面。

比如:

A = []
A.append([1, 2, 3])

结果就是:

A = [[1, 2, 3]]

再来一次:

A.append([4, 5, 6])

结果变成:

A = [[1, 2, 3], [4, 5, 6]]

所以 append 本身很简单,它不负责切、转、读,它只负责:

加进去。


可以把整句分成“生产”和“存放”两部分

这一句:

A.append(list(map(int, input().split())))

可以记成两半:

前半部分:生产一行数据

list(map(int, input().split()))

作用:得到一行整数列表,比如 [1, 2, 3]

后半部分:把这行数据放进 A

A.append(...)

作用:把上面那一行塞进 A


对初学者来说,更推荐你先写成两句

如果你现在觉得一口气写成一大句容易乱,那就先写成两句。

推荐版

row = list(map(int, input().split()))
A.append(row)

这样顺序会清楚很多:

第一句:先读出一行
第二句:再追加进 A

这比直接写成一整句更适合你现在这个阶段。


我们手动模拟一遍完整过程

假设输入是:

1 2 3

现在执行:

row = list(map(int, input().split()))
A.append(row)

第一步:input()

读到:

"1 2 3"

第二步:.split()

变成:

["1", "2", "3"]

第三步:map(int, ...)

逐个转整数,得到相当于:

1, 2, 3

第四步:list(...)

变成:

[1, 2, 3]

于是:

row = [1, 2, 3]

第五步:A.append(row)

如果原来:

A = []

那么执行后:

A = [[1, 2, 3]]

这就是整个流程。


你现在要重点区分两类东西

这是最关键的区分。

第一类:处理输入内容的

这些是“把一行文字变成数字列表”的工具:

  • input()
  • .split()
  • map(int, ...)
  • list(...)

它们负责的是:加工数据


第二类:存数据的

这个是“把加工好的结果放进大列表”的工具:

  • append()

它负责的是:保存结果


所以完整逻辑其实就是一句话

先把这一行处理成列表,再 append 到总列表里。

这句话你一定要记住。


你可以这样强行拆解,帮助自己记忆

把:

A.append(list(map(int, input().split())))

拆成下面这样:

line = input()              # 读一行
parts = line.split()        # 切开
nums = map(int, parts)      # 转整数
row = list(nums)            # 变成列表
A.append(row)               # 塞进 A

你会发现,一点都不神秘。

只是平时为了写得简洁,把它们压缩到一行里了。


记忆时,不要背“长代码”,要背“动作链”

你最该记住的不是字面,而是这个动作顺序:

一行数据的生成流程

读 → 切 → 转 → 装

对应:

input() → split() → map(int, ...) → list(...)

二维数组的存储流程

每次生成一行 → append 进总列表

对应:

row = ...
A.append(row)

给你一个真正实用的记忆口诀

list(map(int, input().split()))

记成:

读一行,切一刀,全转整,装成表。

A.append(row)

记成:

这一行已经弄好了,塞进 A 里。

这比死记代码更有用。


以后你实战时,建议先写“展开版”

在你还不够熟的时候,完全没必要直接写:

A.append(list(map(int, input().split())))

你可以先写展开版:

row = input().split()
row = list(map(int, row))
A.append(row)

甚至更展开:

line = input()
parts = line.split()
row = list(map(int, parts))
A.append(row)

这样最不容易错。

等你写熟了,再压缩。


方法总结

你现在这一步只需要死死抓住下面两点。

第一,嵌套表达式从里往外看

看到:

list(map(int, input().split()))

执行顺序是:

input()
→ split()
→ map(int, ...)
→ list()

不是从左往右机械读。


第二,append 永远是“最后放进去”

看到:

A.append(...)

就理解成:

先把括号里的内容算出来,再放进 A。


本节小结

你现在已经知道这类代码在干什么了,下一步就是建立“顺序感”。

把这两句话背熟就够了:

第一句:
list(map(int, input().split())) = 读一行,切开,转整数,装成列表

第二句:
A.append(row) = 把这一行加到 A 的最后面

这就是全部核心。


练习

这次给你一个很小的练习,只练顺序,不练题目。

练习题

请你自己不用看答案,试着把下面这句代码拆成 3 到 5 行:

A.append(list(map(int, input().split())))

要求你拆完之后,每一行旁边写中文注释,说明这一行在干什么。


提示

你可以按这个思路拆:

  1. 先读一行
  2. 再切开
  3. 再转整数列表
  4. 最后 append 到 A

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇