第二周课程的Elementray Sorts部分练习测验Interview Questions的第3题荷兰国旗问题很有意思。题目的原文描述如下:

Dutch national flag. Given an array of n buckets, each containing a red, white, or blue pebble, sort them by color. The allowed operations are:

  • swap(i,j): swap the pebble in bucket i with the pebble in bucket j
  • color(i)determine the color of the pebble in bucket i

The performance requirements are as follows:

  • At most n calls to color()
  • At most n calls to swap()
  • Constant extra space.

该问题在维基百科上的解释为:

The Dutch national flag problem (DNF) is a computer science programming problem proposed by Edsger Dijkstra.The flag of the Netherlands consists of three colors: red, white and blue. Given balls of these three colors arranged randomly in a line (the actual number of balls does not matter), the task is to arrange them such that all balls of the same color are together and their collective color groups are in the correct order.

本题的限制条件n calls to color()意味着每个元素最多只能访问一次,也就是要求在遍历一次所有元素的情况下完成排序。遍历结束时红色球要全部在数组的左侧,白色球全部在中间,蓝色球全部在右侧,整个数组将被分成三部分。用current记录当前需要访问的球的位置,还需要两个位置记录红-白分界处和白-蓝分界处,用lo来标记白色球的开始位置,hi来标记白色球的结束位置。lo和current起始相同,两个从数组左侧以++方式前进,hi从数组右侧以--方式前进。循环主体设计方式:【后来看到3way-quicksort,发现这个做法与3way-quicksort很像,而且后者代码更清晰简单,特在文末附了3way-quicksort的实现】

1、当current为红色时,如果lo==current,不需要交换位置,二者均前进++一步;如果不相等,意味着current 肯定大于lo,lo和current之间都为白色球,将lo和current位置处的球进行交换,lo处就变成了红色球,current处就变成了白色球,lo需要++前进一步来标志白色球的起始位置,而此时current处的球在之前已经被遍历过(左侧的球均被遍历过),current也需要++前进一步来访问下一个球

2. 当current为白色时,该球位置正确,不需要移动,current直接++前进一步

3. 当current为蓝色时,表明该球应该放置于数组右侧,此时需要和数组右侧hi处的球交换,然后hi处的球就变成了蓝色,并且该蓝色球是已经被访问过的,hi需要往右侧--前进。而此时current处交换过来的球还没有被访问过,故current位置不需要变动,留到下一次循环进行访问。

循环体在current访问完所有的球后结束,也就是current>hi时结束,因为大于hi的节点都是由current遍历交换过来的。

代码实现:

 import java.util.Arrays;
import edu.princeton.cs.algs4.StdRandom; public class DutchNationalFlag {
public static final int RED = 0;
public static final int WHITE = 1;
public static final int BLUE = 2;
private int n;
private int[] buckets;
public int callColorNum = 0;
public int callSwapNum = 0; public DutchNationalFlag(int[] buckets) {
n = buckets.length;
this.buckets = buckets;
} public void sort() {
int lo = 0;
int hi = n - 1;
int current = lo;
while (current <= hi) {
switch(color(current)){
case RED:
if (current != lo)
swap(current, lo);
current++;
lo++;
break;
case WHITE:
current++;
break;
case BLUE:
swap(hi,current);
hi--;
break;
}
}
} private void swap(int i, int j) {
callSwapNum++;
int t = buckets[i];
buckets[i] = buckets[j];
buckets[j] = t;
} private int color(int i) {
callColorNum ++;
return buckets[i];
} public static void main(String[] args) {
int n = 10;
int[] buckets = new int[n];
for (int i = 0; i < n; i++) {
buckets[i] = StdRandom.uniform(3);
}
System.out.println(Arrays.toString(buckets));
DutchNationalFlag dnf = new DutchNationalFlag(buckets);
dnf.sort();
System.out.println("after sort call color+"+dnf.callColorNum+"times, call swap="+ dnf.callSwapNum+"times");
System.out.println(Arrays.toString(buckets));
}
}

思路参考http://www.cnblogs.com/gnuhpc/archive/2012/12/21/2828166.html

3way-quicksort实现:

     public void quickSort3way(){
int lt = 0;
int gt = n - 1;
int i = 0;
while (i <= gt) {
int cc = color(i);
if(cc < WHITE) swap(lt++,i++);
else if(cc > WHITE) swap(i,gt--);
else i++;
}
}

Coursera Algorithms week2 基础排序 练习测验: Dutch national flag 荷兰国旗问题算法的更多相关文章

  1. Coursera Algorithms week2 基础排序 练习测验: Permutation

    题目原文: Given two integer arrays of size n , design a subquadratic algorithm to determine whether one ...

  2. Coursera Algorithms week2 基础排序 练习测验: Intersection of two sets

    题目原文: Given two arrays a[] and b[], each containing n distinct 2D points in the plane, design a subq ...

  3. 2-Color Dutch National Flag Problem

    2-Color Dutch National Flag Problem 问题 a[0..n-1]中包含红元素或蓝元素;重新放置使得 红元素均在蓝元素之前. 循环不变式 每一次循环,a[0...k-1] ...

  4. Coursera Algorithms week2 栈和队列 练习测验: Queue with two stacks

    题目原文: Implement a queue with two stacks so that each queue operations takes a constant amortized num ...

  5. Coursera Algorithms week4 基础标签表 练习测验:Inorder traversal with constant extra space

    题目原文: Design an algorithm to perform an inorder traversal of a binary search tree using only a const ...

  6. Coursera Algorithms week4 基础标签表 练习测验:Check if a binary tree is a BST

    题目原文: Given a binary tree where each 

  7. Coursera Algorithms week4 基础标签表 练习测验:Java autoboxing and equals

    1. Java autoboxing and equals(). Consider two double values a and b and their corresponding Double v ...

  8. Coursera Algorithms week2 栈和队列 练习测验: Stack with max

    题目原文: Stack with max. Create a data structure that efficiently supports the stack operations (push a ...

  9. Coursera Algorithms week1 查并集 练习测验:3 Successor with delete

    题目原文: Given a set of n integers S = {0,1,…,N-1}and a sequence of requests of the following form: Rem ...

随机推荐

  1. Google开源技术protobuf

    1.protobuf简介 protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多.虽然是二进制数 ...

  2. dotnetnuke 7.x登录时不跳到站点设置中的指定页

    查源码发现登录按钮有参数,点击跳到登录页或者弹窗登录,真正登录后会根据传参的url反回.因为皮肤对像没有相应参数,所以只能去掉参数.我是用js去的,偷个懒吧.如下所示: <script type ...

  3. dotnetnuke 添加用户属性 Profile

    if (DotNetNuke.Entities.Profile.ProfileController.GetPropertyDefinitionByName(this.PortalId, "Q ...

  4. ajax不执行success的问题

    有时候经常会遇到ajax请求后台,然后后台返回数据后,不触发ajax的success函数的问题,归根到底,这与ajax的参数设置dataType和后台的返回值的类型有关,现总结如下: 一.后台返回值的 ...

  5. JavaScript学习书签

    JavaScript常用正则表达式 闭包 JavaScipt DOM 变量提升

  6. 关于JS中的方法是否加括号的问题

    js中的方法什么时候加括号什么时候不加括号呢,我们有时候经常就搞不清楚,记住下面这几点就好理解了. 1.函数做参数时都不要加括号. function fun(a){ alert(a); } funct ...

  7. linux下如何限制普通用户更改密码

    问题描述: 为了方便linux管理员对所有用户的进行管理,如何限制普通用户更改密码? 解决方法: 禁止普通用户更改密码: /usr/bin/passwd 若要允许普通用户更改密码: /usr/bin/ ...

  8. 293. [NOI2000] 单词查找树——COGS

    293. [NOI2000] 单词查找树 ★★   输入文件:trie.in   输出文件:trie.out   简单对比时间限制:1 s   内存限制:128 MB 在进行文法分析的时候,通常需要检 ...

  9. Luogu P1041 [2003NOIP提高组]传染病控制

    P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...

  10. 利用open MP获取计算机核心数量的方法

    openMP是一款普遍通用的并行计算编程模型,使用它通常能够充分利用多核计算的优势. 以下是一种能够测试核心数量的方法: std::cout << "parallel begin ...