1 问题描述

问题: 若元素 a,b,c,d,e,f,g 顺序进栈,且出栈顺序是 b,d,c,f,e,a,g 则栈的容量至少是_____

答案:3

2 解法描述与分析

2.1 解法描述

1,2,3,4,5,6… 分别对应 a,b,c,d,e,f…, 记序列长度为 LLL, MMM 为当前最大元素,记SkS_kSk 为第 kkk 步时栈内元素个数, 栈大小的下限为 SaS_aSa,记 VkV_kVk 为第 kkk 个元素的值。求解算法如下

Algorithm 2 依据出栈列表计算所需最少栈空间的算法
step 1: 对出栈序列获得其对应的数列,初始化M=0M=0M=0S0=0S_0 = 0S0=0, Sa=1S_a = 1Sa=1, k=1k= 1k=1.
step 2: 读取第 kkk 个出栈元素的值VkV_kVk .
step 3: 如果第 VkV_kVk 大于MMM,令 Sk=Sk−1+(Vk−M−1)S_k= S_{k-1} + (V_k - M - 1)Sk=Sk1+(VkM1) , 然后令M=VkM = V_kM=Vk ; 否则Sk=Sk−1−1S_k = S_{k-1} - 1Sk=Sk11, MMM 值不变 .
step 4: 比较 SaS_aSaSkS_kSk 的大小,如果 SaS_aSa 小于 SkS_kSk, 则 Sa=SkS_a = S_kSa=Sk .
step 5: 如果 kkk 小于序列长度 LLL, 则 k=k+1k=k+1k=k+1, 并回到 step 2;否则返回SaS_aSa .

对问题有如下的执行过程
step 1: b,d,c,f,e,a,g →\rightarrow 2,4,3,6,5,1,7
执行完 step 1 之后有如下表的执行步,表中已经把 step 2–step 4 合并

kkk VkV_kVkMMM的关系 MMM SkS_kSk SaS_aSa
初始 0 S0S_0S0 = 0 1
1 2 > MMM 2 S1S_1S1 = S0S_0S0 + (2 - 0 - 1 ) = 1 2
2 4 > MMM 4 S2S_2S2 = S1S_1S1 + (4 - 2 - 1) = 2 + 0 = 2 3
3 3 < MMM 4 S3S_3S3 = S2S_2S2 - 1 = 1 3
4 6 > MMM 6 S4S_4S4 = S3S_3S3 + (6 - 4 - 1) = 2 3
5 5 < MMM 6 S5S_5S5 = S4S_4S4 - 1 = 1 3
6 1 < MMM 6 S6S_6S6 = S5S_5S5 - 1 = 0 3
7 7 > MMM 7 S7S_7S7 = S6S_6S6 + (7 - 6 - 1) = 1 3

最后得栈大小下限为 Sa=3S_a = 3Sa=3

2.2 算法分析
2.2.1 算法推导

首先栈的大小的下限 Sa≥1S_a \geq 1Sa1,栈的大小可以通过确定栈中元素最多时来确定,而栈中元素的个数是动态变化的,这有点像湖,水流流入湖中类似于入栈,水从湖中流出,类似于出栈,而确定湖水最高的水平面则类似于确定栈最多元素时的大小。通过确定入栈元素个数和出栈元素个数,便可以确定栈中元素最多时的个数。当元素进入之后立即弹出,一个栈空间就够了,当不立即弹出时,则需要更多的栈空间。如果第k步时栈的中元素的个数为 SkS_kSk , 出栈的最大元素为 MMM, 则由 Vk+1V_{k+1}Vk+1MMM 的大小关系便可以确定入栈元素的个数:若 Vk+1>MV_{k+1}>MVk+1>M 则处于 Vk+1V_{k+1}Vk+1MMM 之间的元素一定被会压入栈中,Vk+1V_{k+1}Vk+1 本身入栈后立即弹出,则此时栈的大小 Sk+(Vk+1−M−1)S_k + (V_{k+1} - M - 1)Sk+(Vk+1M1),若 Vk+1<MV_{k+1} < MVk+1<M 则说明Vk+1V_{k+1}Vk+1 是从栈中弹出的且没有入栈操作,此时 Sk−1S_k - 1Sk1. 由此可得到如下递推关系

Sk+1={Sk+(Vk+1−M−1)Vk+1>MSk−1Vk+1<MS_{k+1}=\left\{ \begin{aligned} &S_k + ( V_{k+1} - M - 1) &V_{k+1} > M \\ &S_k - 1 & V_{k+1} < M \end{aligned} \right.Sk+1={Sk+(Vk+1M1)Sk1Vk+1>MVk+1<M

最后可得Sa=Max(S1,...,SL)+1S_a = Max(S_1,..., S_L) + 1Sa=Max(S1,...,SL)+1, 其中LLL 为数列的大小,之所以要加1,是立即入栈出栈的元素也需要一个空间。

2.2.2 算法复杂性分析

时间复杂性 O(n), 空间复杂性 O(1).

3 算法的程序实现

3.1 python 实现
def find_stack_needed_size(in_stack_list, out_stack_list):
    item_dict = {v:i+1 for i,v in enumerate(in_stack_list)}
    S_k,S_a = 0,1
    M = 0
    k = 1
    for item in out_stack_list:
        if item_dict[item] > M:
            S_k = S_k + (item_dict[item] - M - 1)
            M = item_dict[item]
            if S_k + 1 > S_a: S_a = S_k + 1
        else:
            S_k = S_k - 1
        print('k={0}  M={1} S_{0}={2} S_a={3}'.format(k, M, S_k, S_a))
        k += 1
    return S_a

测试:

In : find_stack_needed_size(['a','b','c','d','e','f','g'],['b','d','c','f','e','a','g'])
k=1  M=2 S_1=1 S_a=2
k=2  M=4 S_2=2 S_a=3
k=3  M=4 S_3=1 S_a=3
k=4  M=6 S_4=2 S_a=3
k=5  M=6 S_5=1 S_a=3
k=6  M=6 S_6=0 S_a=3
k=7  M=7 S_7=0 S_a=3
Out: 3
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐