(1) 出栈序列判定
答案:第一个 {2, 3, 1, 6, 4, 7, 5, 8} 不可以;第二个 {2, 3, 1, 4, 6, 5, 7, 8} 可以。
判定方法:模拟"按 1, 2, 3, ... 顺序入栈,按目标序列要求出栈"的过程,若某一步出栈要的元素不在栈顶就判失败。
序列 1 模拟(输入 1..n 依次入栈):
| 操作 |
栈状态(右为顶) |
已出栈 |
| push 1 |
[1] |
— |
| push 2 |
[1, 2] |
— |
| pop → 2 ✓ |
[1] |
2 |
| push 3 |
[1, 3] |
2 |
| pop → 3 ✓ |
[1] |
2,3 |
| pop → 1 ✓ |
[] |
2,3,1 |
| push 4 |
[4] |
2,3,1 |
| push 5 |
[4, 5] |
2,3,1 |
| push 6 |
[4, 5, 6] |
2,3,1 |
| pop → 6 ✓ |
[4, 5] |
2,3,1,6 |
| 要 pop → 4,但栈顶是 5 ✗ |
— |
— |
结论:序列 1 不可由栈得到。
序列 2 模拟——按相同方法逐步推,可以走通至最后 P_8 = 8 出栈,全程无矛盾。具体过程可由读者自行验证(关键点:4 直接出后再 push 5,6,先 pop 6 再 pop 5)。结论:序列 2 可以由栈得到。
(2) 不能由栈得到的序列中 P_i, P_j, P_k 的大小关系
答案:存在 i < j < k 满足 Pj<Pk<Pi(即 P_i 最大、P_j 最小、P_k 居中),下标递增但值呈"大-小-中"模式。
证明(反证):若出栈序列出现 i<j<k 满足 Pi>Pk>Pj(即 Pj<Pk<Pi),考察 P_i 出栈那一刻——
- Pj>Pi?不,Pj<Pi。所以 P_j 在 1..n 中比 P_i 小,P_j 入栈在 P_i 之前(按 1..n 顺序入栈,小数先入);
- 既然 P_j 入栈在 P_i 之前,且 P_j 在 P_i 之后才出(因为 i < j),P_i 出栈时 P_j 必在栈中且在 P_i 下方;
- 同样地,Pk<Pi,P_k 也是入栈在 P_i 之前。但 Pk>Pj,且 P_k 比 P_j 后出(j < k),所以 P_i 出栈时 P_k 在栈中且在 P_j 上方、P_i 下方。
P_i 出栈后,栈顶是 P_k(不是 P_j,因为 P_k 在 P_j 上方)。要让 P_j 在 P_k 之前出(j < k 意味着 P_j 先出)就违反栈 LIFO——栈顶必先出,即 P_k 应先于 P_j 出栈。矛盾。
用序列 1 验证:{2, 3, 1, 6, 4, 7, 5, 8}。取 i=4, j=5, k=7(1-indexed):P4=6,P5=4,P7=5。P5<P7<P4(4 < 5 < 6)✓——刚好是不可由栈得到的关键三元组。
(3) n = 4 时以 2 开头的出栈序列个数
答案:5 个,分别是 {2,1,3,4}, {2,1,4,3}, {2,3,1,4}, {2,3,4,1}, {2,4,3,1}。
推导:P_1 = 2 意味着已 push 1、push 2、pop 2,当前栈 = [1],待入 = [3, 4]。从此状态出发的所有合法栈操作:
[1] | 待入 [3,4]
/ \
pop 1 (→ 21..) push 3 (→ 23..)
| |
[] | [3,4] [1,3] | [4]
/ \ / \
...2,1,3,4 ...2,1,4,3 pop 3 push 4
| |
[1] | [4] [1,3,4] | []
/ \ |
pop 1 push 4 pop 4,3,1 → 2,4,3,1
| |
..2,3,1,4 ..2,3,4,1
共 5 条到达终点的路径,对应 5 个序列:
| # |
序列 |
| 1 |
2, 1, 3, 4 |
| 2 |
2, 1, 4, 3 |
| 3 |
2, 3, 1, 4 |
| 4 |
2, 3, 4, 1 |
| 5 |
2, 4, 3, 1 |
(4) 用 M(n=k−1 时的总数)表达 n=k 的几个数量
设 n 个数依次入栈出栈的合法出栈序列总数为 Cn(恰好是卡特兰数 Catalan number)。题面给定 Ck−1=M。
以 1 开头的出栈序列数
答案:M 个。
P_1 = 1 意味着 push 1 后立刻 pop 1,状态变为"栈空 + 待入 2..k"——这正是 n = k − 1 个数(2, 3, ..., k)的独立栈操作问题,序列数 = Ck−1=M。
以 2 开头的出栈序列数
答案:M 个。
P_1 = 2 意味着 push 1、push 2、pop 2,状态:栈 = [1],待入 = [3, ..., k],还要再出 k−1 个数。
记 1 在 P_t 位置出栈(t∈{2,3,...,k})。在 P_1 与 P_t 之间出栈的 t−2 个数必为 {3, ..., t} 中元素(因为 1 在栈底,能出栈的"上层"必是 3..t);P_t 之后出栈的 k−t 个数是 t+1..k。这两段彼此独立,分别对应 Ct−2 和 Ck−t 种组合。求和:
以 2 开头的数=t=2∑kCt−2⋅Ck−t=j=0∑k−2Cj⋅Ck−2−j
由卡特兰数卷积恒等式 Cn=∑j=0n−1Cj⋅Cn−1−j,把 n=k−1 代入即得右式 = Ck−1=M。
与 (3) 验证:n = 4 时以 2 开头 = C3 = 5 ✓。
n = k 时的总出栈序列数
答案:Ck=k+14k−2M。
推导——卡特兰数的递推 Ck 与 Ck−1 的比值:
Ck−1Ck=(k−12k−2)/k(k2k)/(k+1)=k+1k⋅k⋅k(2k)(2k−1)=k+12(2k−1)=k+14k−2
所以 Ck=k+14k−2⋅Ck−1=k+1(4k−2)M。
直观验证(k=4,M=5):C4=514⋅5=14 ✓(卡特兰数 1, 1, 2, 5, 14, 42 ...)。
编者注(生僻术语):n 个数依次入栈所有合法出栈序列数 = 第 n 个卡特兰数 Cn=n+11(n2n)。这一结果有多种等价模型——括号匹配、不相交弦、二叉树形态、网格路径等。考研只考"出栈序列计数"这一种,记住 C4=14、C5=42 这几个常用值就能秒应对小 n 题;大 n 用递推 Ck=k+14k−2Ck−1。