IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 【数据结构与算法/组合数学】出栈序列的个数问题详解 -> 正文阅读

[人工智能]【数据结构与算法/组合数学】出栈序列的个数问题详解

假设有一个入栈序列 a 1 , a 2 , ? ? , a n a_1,a_2,\cdots,a_n a1?,a2?,?,an?,现在求它有多少种出栈序列。

例如,对于入栈序列 1 , 2 , 3 1,2,3 1,2,3,我们有 5 5 5种出栈序列:
① 3 , 2 , 1 ①3,2,1 3,2,1push 1,push 2,push 3,pop 3,pop 2,pop 1
② 2 , 3 , 1 ②2,3,1 2,3,1push 1,push 2,pop 2,push 3,pop 3,pop 1
③ 1 , 3 , 2 ③1,3,2 1,3,2push 1,pop 1,push 2,push 3,pop 3,pop 2
④ 1 , 2 , 3 ④1,2,3 1,2,3push 1,pop 1,push 2,pop 2,push 3,pop 3
⑤ 2 , 1 , 3 ⑤2,1,3 2,1,3push 1,push 2,pop 2,pop 1,push 3,pop 3

现在我们考虑对任意 n n n的情况。令 f ( i ) f(i) f(i)代表长度为 i i i的序列的出栈序列个数。则我们要求的就是 f ( n ) f(n) f(n)

显然, f ( 0 ) = f ( 1 ) = 1 f(0)=f(1)=1 f(0)=f(1)=1,因为没有元素和只有一个元素的时候都只有一种顺序。有 n n n个元素时,问题太大,我们采用分而治之的思想,递归求解。考虑入栈的第一个元素 a 1 a_1 a1?在出栈序列中的位置。设 a 1 a_1 a1?是第 j j j个出栈的,则 a 2 ~ a j a_2\sim a_j a2?aj?必须在 a 1 a_1 a1?之前出栈。这个性质是十分关键的。要理解这个性质,必须运用栈的LIFO (Last In First Out)(后进先出)特征。因为 a 2 ~ a j a_2\sim a_j a2?aj? a 1 a_1 a1?后入栈,那就比 a 1 a_1 a1?先出栈。换句话说, a 2 ~ a j a_2\sim a_j a2?aj?一定是压在 a 1 a_1 a1?头顶的,如果它们不出去, a 1 a_1 a1?就没法出去。当 a 1 a_1 a1?出去时,栈一定是空的。那么下面就简单了。现在 a 1 a_1 a1?把出栈序列分割为两部分 a 2 ~ a j a_2\sim a_j a2?aj? a j + 1 ~ a n a_{j+1}\sim a_n aj+1?an?。我们看到,前一部分和后一部分是相互独立的。而前一部分的出栈顺序个数为 f ( j ? 1 ) f(j-1) f(j?1),后面一部分的出栈顺序个数为 f ( n ? j ) f(n-j) f(n?j)。因为二者互不影响,所以贡献的总出栈顺序个数为 f ( j ? 1 ) × f ( n ? j ) f(j-1)\times f(n-j) f(j?1)×f(n?j)如果你不理解,可以先考虑前一部分有一个固定的顺序,那么后一部分有 f ( n ? j ) f(n-j) f(n?j)种顺序;再令前一部分的顺序变化,共有 f ( j ? 1 ) f(j-1) f(j?1)种变化,所以结果就是 f ( j ? 1 ) f(j-1) f(j?1) f ( n ? j ) f(n-j) f(n?j),即 f ( j ? 1 ) × f ( n ? j ) f(j-1)\times f(n-j) f(j?1)×f(n?j)好了,这就是对于一个固定的 j j j的顺序个数。再令 j j j取到 1 ~ n 1\sim n 1n,用加法原理把所有可能性加起来,就是 f ( n ) = f ( 0 ) f ( n ? 1 ) + f ( 1 ) f ( n ? 2 ) + ? + f ( n ? 1 ) f ( 0 ) = ∑ j = 1 n f ( j ? 1 ) f ( n ? j ) \begin{aligned}f(n)&=f(0)f(n-1)+f(1)f(n-2)+\cdots+f(n-1)f(0)\\&=\sum\limits_{j=1}^nf(j-1)f(n-j)\end{aligned} f(n)?=f(0)f(n?1)+f(1)f(n?2)+?+f(n?1)f(0)=j=1n?f(j?1)f(n?j)?这里要求 n ≥ 2 n\ge2 n2。这个递推公式解起来挺麻烦的,我们直接给出结论。事实上, f ( n ) f(n) f(n)就是卡特兰数(Catalan Numbers),记作 C n C_n Cn?(不要与组合数混淆QwQ),它的的公式是 C n = ( 2 n ) ! ( n + 1 ) ! n ! = 1 n + 1 C n 2 n C_n=\frac{(2n)!}{(n+1)!n!}=\frac{1}{n+1}C_n^{2n} Cn?=(n+1)!n!(2n)!?=n+11?Cn2n?可以验证它满足我们推出的递推公式。当 n = 3 n=3 n=3时, C 3 = 6 ! 4 ! 3 ! = 720 24 × 6 = 120 24 = 5 C_3=\frac{6!}{4!3!}=\frac{720}{24\times6}=\frac{120}{24}=5 C3?=4!3!6!?=24×6720?=24120?=5,与我们在开头提到的 1 , 2 , 3 1,2,3 1,2,3 5 5 5种出栈序列相符。


出栈序列的个数问题与很多问题等价。例如,求 n n n个左括号和 n n n个右括号能组成多少合法的括号序列。这里的合法指的是每个括号都有配对。 n = 3 n=3 n=3时有 5 5 5种: ( ( ( ) ) ) , ? ( ( ) ( ) ) , ? ( ( ) ) ( ) , ? ( ) ( ) ( ) , ? ( ) ( ( ) ) ((())),\ (()()),\ (())(),\ ()()(),\ ()(()) ((())),?(()()),?(())(),?()()(),?()(()),恰与 3 3 3个元素的出栈序列个数相同。这种括号序列问题的答案也是卡特兰数。


最后附上求任一入栈序列的所有出栈序列的代码:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int n, ans;
string s, a;
vector<char> stk;

void dfs(int i)
{
    // --- pop
    if(!stk.empty())
    {
        a.push_back(stk.back());
        if(a.size() == n)
            cout << a << '\n', ++ans;
        stk.pop_back();
        dfs(i);
        stk.push_back(a.back());
        a.pop_back();
    }
    // --- push
    if(i < n)
    {
        stk.push_back(s[i]);
        dfs(i + 1);
        stk.pop_back();
    }
}

int main()
{
    cout << "Please enter the in-stack "
        "sequence:\n>>> ";
    // e.g. ABCED
    cin >> s;
    n = s.size();
    dfs(0);
    cout << "Totally " << ans << " sequences.\n";
    return 0;
}

例如

Please enter the in-stack sequence:
>>> ABCD
ABCD
ABDC
ACBD
ACDB
ADCB
BACD
BADC
BCAD
BCDA
BDCA
CBAD
CBDA
CDBA
DCBA
Totally 14 sequences.
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:08:21  更:2022-03-17 22:12:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:36:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码