Dutch National Flag 问题

  • 问题描述
    • 思考
      • 快速排序
      • 桶排序
      • Dutch NF分类算法
  • Dutch NF 算法
    • 代码描述
      • 两色DutchNF
      • 三色Dutch NF问题
  • ref

Dutch N.F. 荷兰国旗问题,是一类分类的问题。需要在给定的一个集合中,将三类点分开。

Dutch National Flag 问题_第1张图片

问题描述

我们在集合中给定了三类点,分别是red,white,blue,分别用1,2,3表示。我们需要将这三类点按照一定的顺序进行排序,最后让排序后的点组成荷兰国旗。

即,给定了集合{1,2,3,2,1,2,3,2,1,2,3,3,2,1,1,1,2,3,2,1,2,3,1,2,…}我们需要将其整理成为{1,1,…,2,2,…3,3,…}。本质上来讲是一个分类的问题。

思考

快速排序

首先这类问题同样也可以看做一类排序的问题,利用快速排序的方法,同样可以得到分类的过程,但是我们仅仅需要对一个大类进行区分,而快排则将所有的数字都进行了一次排序,做了一些额外的工作,直观上来讲并不是最合适的方法,但是其O(nlogn)的复杂度是可以接受的。

桶排序

有同学可能会想到,我们用桶排序就可以达到O(n)的时间复杂度,但是在某些情况我们用1,2,99999来表示分类,那么空间的开销将会非常大,因此这也不是很合适的解。

Dutch N.F分类算法

本文将介绍Dutch N.F分类算法,该算法可以在O(n)的时间复杂度,O(1)空间复杂度情况下解决这个问题。

Dutch N.F 算法

Dutch N.F算法的精髓在于分区,增长。记住这两点,就搞定了这个算法。

分区:我们现在想想已经有一个分类好的数组了。但是在现实情况下,我们却有很多工作没有做,因此,需要引入一个未知区域的概念。现在就可以数组分为[1,1,….,未知区域,2,2,…]。未知区域表示,待我们处理的区域,通过减少这个区域,我们就可以逐渐完成一个分类的工作。

增长:通过分区1和分区2我们可以收缩未知区域,当未知区域到0的时候,我们可以得到分类结果。这个过程中,我们需要用到三个指针来表示这三个区域的变换。buttom,top,mid

代码描述

两色Dutch.N.F

我们首先通过一个简单的两色Dutch N.F.引入问题以及解决方法。

现在我们有一个长度为N的数组a[],里面放着两种颜色(假设是红色和蓝色)。现在0表示红色,1表示蓝色。那么a[]中的元素来自{0,1}集合。现在,我们利用分区的方式,对其进行分区:

1、a[0,…,L] 我们记为红色区域
2、a[L+1,…,H-1] 我们记为未知区域
3、a[H,…,N-1]我们记为蓝色区域。

算法流程:

L := 0; H = N-1;
while L <= H do
Invariant: a[0..L] are all zero and a[H,..,N-1] are all one; a[L..H] are unknown.
if a[L] = 0 then L++
else swap a[L] and a[H]; H--

三色Dutch N.F.问题

现在我们有红白蓝三种颜色,分别用1,2,3表示。

三色Dutch N.F. 问题就需要我们使用三个指针buttom,top,mid来解决。

  • buttom: 表示第一类已经分类序列的顶部
  • top:第三类已经分类好的序列底部
  • mid:未知区域探索指针

同样, 现在对区域进行划分:

1、a[0,…buttom] 红色区域
2、a[buttom+1,…,mid-1] 白色区域
3、a[mid,..,top-1] 未知区域
4、a[top,…,N-1] 蓝色区域

算法:

buttom := 0; Mid := 0; top := N-1;
while Mid <= top do
Invariant: a[0..buttom]=1 and a[buttom+1..Mid-1]=2 and a[top..N-1]=3; a[Mid..top-1] are unknown.
case a[Mid] in

        0: swap a[buttom] and a[Mid]; buttom++; Mid++
        1: Mid++
        2: swap a[Mid] and a[top]; top--

算法很好理解,探索指针mid从0开始探索

发现是一个第一区域的数,就与第一区域的顶部数据(这个数据不被第一区域包含,其实为第二区域数据)交换。

发现是第二区域的数,跳过

发现是第三区域的数据,和顶部最底层的数据交换。

注意top指向的数,其实是没有验证过的,因此在mid==top的情况下还需要做一次验证。

ref

http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Flag/

你可能感兴趣的:(算法问题)