【Python】二进制序列生成与输出
题目要求:
给定一个正整数N,你需要输出所有长度为N的二进制序列(即只包含 0 和 1 的字符串)。
输出顺序:必须按照字典序(从小到大)排列。例如,当 $N=2$ 时,顺序应为
00,01,10,11。格式:每行输出一个二进制字符串。
解题方法限制
- 递归回溯法(Recursive search/backtracking)。
- 二进制加 1 法(通过模拟二进制加法从 $0$ 一直加到 $2^N-1$)。
| 输入 | 输出 |
|---|---|
| 2 | 00 01 10 11 |
我写的代码:
1 | haha = int(input()) |
巧妙地利用了多重循环遍历嵌套,以及后面的切片操作
这就是所谓的力大飞砖
现在来看正确的写法
“二进制加 1”法
1 | n = int(input()) |
这种方法的逻辑是什么?
题目需要我输出所有长度为N的二进制序列,而这些序列恰好是把从 0 到 $2^n-1$ 的所有十进制数字,依次转化为二进制。
1. 1 << n:极其高效的“$2^n$”计算器
<< 是左移运算符(Bitwise Left Shift)。这个操作在 C 语言里也是一模一样的
它的核心意思是:把数字 1 的二进制形式,整体向左移动 n 位,右边空出来的位置补零。
我们来推演一下:
数字 1 的二进制就是 1。
- 如果
n = 1:1 << 1,二进制变成10,换算成十进制就是 2 ($2^1$)。 - 如果
n = 2:1 << 2,二进制变成100,换算成十进制就是 4 ($2^2$)。 - 如果
n = 3:1 << 3,二进制变成1000,换算成十进制就是 8 ($2^3$)。
所以,1 << n 在数学上等价于 $2^n$。
代码里的 range(1 << n),如果输入 $N=3$,就等价于 range(8),这会让变量 i 从 0 一直遍历到 7。这刚好覆盖了长度为 3 的二进制序列对应的所有十进制数。
2. f"{i:0{n}b}":Python 里的超级“printf”
这是 Python 里的 f-string(格式化字符串),作用类似于 C 语言里的 printf,但功能更强大。
在 C 语言里,如果你想输出一个固定宽度、前面补零的十进制数,你会写 printf("%04d", i)。但是在标准的 C 语言(C23 标准之前)里,并没有直接输出二进制的占位符(没有 %b 这种东西),真要输出二进制,还得自己写个循环用掩码逐位提取 0 和 1。
而 Python 把这件事直接做成了内置功能。我们把 {i:0{n}b} 拆开来看:
f"...":外面的f告诉 Python,这不是一个普通的字符串,里面如果有大括号{},要把它当成变量或表达式去计算。i:这是当前循环到的十进制数字(比如 0, 1, 2, 3…)。::这是一个分隔符。冒号左边是要处理的“变量名”,冒号右边是“格式化规则”。b:代表 binary(二进制)。这会让 Python 自动把十进制的i转换成二进制。比如i是 2,转出来就是"10"。0{n}:这是控制“对齐和补零”的。{n}:表示输出的总宽度。这里巧妙地嵌套了另一个变量n(也就是我们输入的序列长度)。0:表示如果二进制字符串的长度不够这个宽度,就在左边补零。
”递归回溯“法
1 | def generate_binary(n, current_str=""): |
为什么传了一个参数,却有两个变量?
在 Python 里,current_str="" 这个语法叫做默认参数。
以前写 C 语言的时候,函数如果定义了接收两个参数,调用时就必须老老实实传两个,少一个编译器都会报错。但 Python 很灵活,它允许你给参数“兜底”。当你只传了 n 的时候,Python 发现你没传第二个参数,就会自动帮你把 current_str 赋值为默认的空字符串 ""。
然而,默认参数不会导致变量被重新初始化,默认参数就像是备胎(兜底),只有你不给它传值的时候,它才会起作用;一旦你传了值,它就乖乖让位



