编程之法:面试和算法心得(荷兰国旗)

内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java

题目描述

拿破仑席卷欧洲大陆之后,代表自由,平等,博爱的竖色三色旗也风靡一时。荷兰国旗就是一面三色旗(只不过是横向的),自上而下为红白蓝三色。

该问题本身是关于三色球排序和分类的,由荷兰科学家Dijkstra提出。由于问题中的三色小球有序排列后正好分为三类,Dijkstra就想象成他母国的国旗,于是问题也就被命名为荷兰旗问题(Dutch National Flag Problem)。

下面是问题的正规描述: 现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右,依次是一些红球、一些白球、一些蓝球。

分析与解法

初看此题,我们貌似除了暴力解决并无好的办法,但联想到我们所熟知的快速排序算法呢?

我们知道,快速排序依托于一个partition分治过程,在每一趟排序的过程中,选取的主元都会把整个数组排列成一大一小的部分,那我们是否可以借鉴partition过程设定三个指针完成重新排列,使得所有球排列成三个不同颜色的球呢?

解法一

通过前面的分析得知,这个问题类似快排中partition过程,只是需要用到三个指针:一个前指针begin,一个中指针current,一个后指针end,current指针遍历整个数组序列,当

  1. current指针所指元素为0时,与begin指针所指的元素交换,而后current++,begin++ ;
  2. current指针所指元素为1时,不做任何交换(即球不动),而后current++ ;
  3. current指针所指元素为2时,与end指针所指的元素交换,而后,current指针不动,end-- 。

为什么上述第3点中,current指针所指元素为2时,与end指针所指元素交换之后,current指针不能动呢?因为第三步中current指针所指元素与end指针所指元素交换之前,如果end指针之前指的元素是0,那么与current指针所指元素交换之后,current指针此刻所指的元素是0,此时,current指针能动么?不能动,因为如上述第1点所述,如果current指针所指的元素是0,还得与begin指针所指的元素交换。

ok,说这么多,你可能不甚明了,直接引用下gnuhpc的图,就一目了然了:

public static void solution(int arr[])
    {
        int begin = 0;
        int current = 0;
        int end = arr.length-1;
        while(current<end)
        {
            if(arr[current]==0)
            {
                int temp = arr[begin];
                arr[begin] = arr[current];
                arr[current] = temp;
                begin++;
                current++;
            }
            if(arr[current]==1)
            {
                current++;
            }
            if(arr[current]==2)
            {
                int temp = arr[end];
                arr[end] = arr[current];
                arr[current] = temp;
                end--;
            }
        }
    }

原文地址:https://www.cnblogs.com/icysnow/p/8270244.html

时间: 2024-10-09 08:37:38

编程之法:面试和算法心得(荷兰国旗)的相关文章

编程之法----面试和算法心得

第1章 字符串 1.1 字符串的旋转 输入一个英文句子,翻转句子中单词的顺序.要求单词内字符的顺序不变,句子中单词以空格符隔开.为简单起见,标点符号和普通字母一样处理.例如:若输入"I am a student.",则输出"student. a am I". #include <stdio.h> void ReverseString(char *s, int from, int to); int main(int argc, const char * a

我的新书《编程之法:面试和算法心得》已经上市

我的新书<编程之法:面试和算法心得>已经上市 经过一天一天.一月一月.一年一年漫长的等待,我的新书终于上架开卖了! 异步社区:http://www.epubit.com.cn/book/details/4051.互动出版网(7.7折且包邮且移动端首单再减5元):http://product.china-pub.com/4880112.京东预售:http://item.jd.com/11786791.html,很快就能抢购. 1 新书上市7天 10月13日晚上,拿到<编程之法>第一本

编程之法:面试和算法心得(寻找和为定值的多个数)

内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 输入两个整数n和sum,从数列1,2,3.......n 中随意取几个数,使其和等于sum,要求将其中所有的可能组合列出来. 分析与解法 解法一 注意到取n,和不取n个区别即可,考虑是否取第n个数的策略,可以转化为一个只和前n-1个数相关的问题. 如果取第n个数,那么问题就转化为"取前n-1个数使得它们的和为sum-n",对应的代码语句就是sumOfkNumber(sum - n, n - 1): 如果

编程之法section II: 2.2 和为定值的两个数

====数组篇==== 2.2 求和为定值的两个数: 题目描述:有n个整数,找出其中满足两数相加为target的两个数(如果有多组满足,只需要找出其中一组),要求时间复杂度尽可能低. 解法一: 思路:开散列映射,空间换时间, 查找耗时o(n) Writer: zzq Function: 求和为定值的两个数. 方法一: 开散列映射(哈希表). 1) 用哈希表Hashmap先把数组中的数字和对应的下标进行存储,(键,值)=(具体数值,对应下标): 2) 遍历数组,对loss=target-nums[

快速排序深入之荷兰国旗问题

一.序言 在使用partition-exchange排序算法时,如快速排序算法(即使选择了一个好的关键元素pivot values),我们往往面临一个很尴尬的境地--当排序对象中有很多重复的元素,partition-exchange排序算法表现很不尽如人意.当所有元素都相等时,这就特别容易理解了.在每次递归中,左边部分是空的(没有元素比关键元素小),而右边部分只能一个一个递减移动.结果导致耗费了二次方时间来排序相等元素.为了解决这个问题(有时叫做荷兰国旗问题),我们详细介绍下解决这个问题的方法.

编程之美2.13 子数组最大乘积

问题描述: 给定一个长度为N的整数数组,只允许用乘法,不能用除法,计算任意(N-1)个数的组合乘积中最大的一组,并写出算法的时间复杂度. 解法: 1.暴力解法------O(n^2) 2.前后缀法------O(n) 3.统计法--------O(n) 具体思路和代码: 1.暴力解法: 思路:利用两层循环,依次删掉一个,其余的做乘法,计算出最大的. 代码: 1 int s1(int A[], int n) 2 { 3 int s = 1; 4 int max; 5 for(int i = 1;

Java 编程之美:并发极速赛车平台出租编程高级篇

借用 Java 并发极速赛车平台出租haozbbs.comQ1446595067 编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了. 相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作的顺序是不可预期的. 并发编程相比 Java 中其他知识点学习起来门槛相对较高,学习起来比较费劲,从而导致很多人望而却步: 而无论是职场面试和高并发高流量的系统的实现却都还离不开并发编程,从而导致能够真正掌握并发编程的人才成为市场比较迫

扯谈网络编程之Tcp SYN flood洪水攻击

简介 TCP协议要经过三次握手才能建立连接: (from wiki) 于是出现了对于握手过程进行的攻击.攻击者发送大量的FIN包,服务器回应(SYN+ACK)包,但是攻击者不回应ACK包,这样的话,服务器不知道(SYN+ACK)是否发送成功,默认情况下会重试5次(tcp_syn_retries).这样的话,对于服务器的内存,带宽都有很大的消耗.攻击者如果处于公网,可以伪造IP的话,对于服务器就很难根据IP来判断攻击者,给防护带来很大的困难. 攻与防 攻击者角度 从攻击者的角度来看,有两个地方可以

编程之美2.14 求数组的子数组之和的最大值

问题描述: 一个有N个整数元素的一维数组(A[0], A[1], A[2],...,A[n-1]),这个数组当然有很多子数组,那么子数组之和的最大值是什么呢? 解法: 1. 暴力解法-------O(N^3) 2. 改进版暴力解法-------O(N^2) *3. 分治算法-------O(NlogN)(暂时未去实现) 4. 数组间关系法-------O(N) 具体思路和代码: 1.暴力解法 思路:Sum[i,...,j]为数组第i个元素到第j个元素的和,遍历所有可能的Sum[i,...,j].