荷兰国旗问题

来源:互联网 发布:修改apk布局软件 编辑:程序博客网 时间:2024/04/30 00:04

刚才在严蔚敏的数据结构习题上看到的这个题。看了几篇博客。貌似都没有结合数据结构的意思来解释。

让我有种冲动写篇文章。。就把这当作我的第一篇博文吧。

 

问题描述:

荷兰国旗问题 ,设有一个仅有红白蓝三种颜色的条块组成的条块序列。请编写一个时间复杂度为O(n)的算法,使得这些条块按红、白、蓝的顺序排好,即排成荷兰国旗的图案。

 

解析:

算法一:

首先复杂度为O(n)。这很容易让人想到扫一遍然后放入3个栈中。这样空间复杂度就为O(3*n)。

其实这种算法用到了基数排序的思想。先设置判断条件。把符合条件的放入相应栈中,然后按序取出。

虽然看上去算法不稳定。由于只有颜色这一种区分,所以取出的顺序可以随便取。

优点:

容易想到。实现不复杂,只用设置3个栈,并且标号就行了。

缺点:

空间浪费大。而实际上元素移动的次数为2n。比下面说到的方法要多。

 

 

算法二:

有了算法一,我们能不能缩小空间的使用呢?答案是可以。

因为简单一看。如果我们把栈设在原始的数组中的话。是不是就可以节约3n的空间了?

那么怎样把栈塞到原始数组中呢?其实只用多扫描一遍原始数组就可以了。记录下rflag wflag bflag的次数就可以了!

如此以来。3个flag变量就成了栈的top变量了!

然后开始扫描3个变量的位置,如果是对应相同,那么就自加。如果不是,就找当前位置的颜色放到对应的栈中。

比方说红色栈顶事蓝色。那么就和对应的bflag所处位置上元素交换。

然后再来判断栈顶元素。如果是红色。那么OK。如果是白色那么就继续交换。直到为红色为止。

如果满了的话就把wflag换成rflag的位置。那么就只和bflag交换了。

优点:

空间大幅减少。相对算法一的移动次数相对减少,大概是n样子(似乎再复杂的情况交换次数也是n,有兴趣的可以自己画画)。

缺点:

实现比较复杂。逻辑也相对前面的复杂一点。

 

算法三:

有了算法二,又没办法让2n次扫描变成n次呢?答案也是确定的~~~

假如我们只设置两个栈。一个红,一个蓝。那么我们遇到蓝栈底就放到最右,红栈底放到最左。

再设置一个中间变量就OK了~

如何实现呢?

和算法二类似。红蓝两个栈顶都不是对应的红蓝。而是其他颜色。

设置中间变量来扫描数据。是红色,就放入红栈中。是蓝色就放入蓝栈中。

如果遇到白色就直接跳过吧~因为白色永远在中间,不可能入栈~

当bflag==中间变量&&中间变量所指向的地址值为白色,那么程序结束。

优点:

简单。实现方便。空间占用少。

缺点:
仔细想想,如果要确定扫描次数,似乎也是2n。所以比较上不占优。

原创粉丝点击