July收集荷兰国旗问题之三路partition
这道题目和分成两块的partition的扩展。比如有一堆0 1 2 数字组成的数组,要分成 00 00 11 1 1 222 2这样的顺序的。
利用lumoto版的partition能够非常好的解决,比hoare好多了。并且直接利用loop invariant,变成i j k三个指针,[low,i]=0 [i+1,j]=1, [j+1,k-1]=2, 里面假设新来2的话,直接k++,
假设是1的话,须要和a[j+1] swap, 同一时候j++, 假设0的话。须要先和a[i+1] swap i++, 然后和 a[j+1] swap j++, 因此算法例如以下:
void NertherlandFlags(int *a, int n)
{
int low=0,high=n-1;
int i=low-1,j=low-1;
for(int k=low;k<=high;k++)
{
if(a[k]==2) ;
else if(a[k]==1)
{
j++;
swap(a[j],a[k]);
}
else if(a[k]==0)
{
i++;
swap(a[i],a[k]);
j++;
swap(a[j],a[k]);
}
}
}
代码比較好写,感觉这都是一类题,
1.快排的partition。注意留一个pivot,算导是留最后一个,所以loop到high-1就停了,里面和pivot比。最后加一次swap把pivot放中间
loop invariant: [low,i] <pivot, [i+1, j-1]>pivot, =放那边都行。exit loop时 j=high, 最后把swap跳进来
2.奇偶排序,整个区间划分为左奇右偶。和%2=0 =1比。loop 到high,
loop invariant: [low,i] 奇, [i+1, j-1]偶, exit时 j=high+1, 包括整个区间了
3.荷兰国企问题,整个区间划分为0 1 2 (红 黄 蓝三块), loop 到high,
loop invariant: [low,i] 0, [i+1, j] 1, [j+1, k-1] exit时 j=high+1, 包括整个区间了
抱歉大家,这道荷兰国旗代码有bug。我才知道的。后经过分析主要是前面仅仅有2 或者0 2时,假设来了0,后面swap(a[j],a[k]) 会多交换一次使得交换回去,所以假设仅仅有0的情况。事实上不须要交换,而swap(a[j],a[k]) swap(a[j],a[k])都是子交换,因此1次两次不影响。于是统一到一起就是没有1区间的时候,也即[i+1,j]区间空,依据性质最多相差1。因此是i==j的时候出错,所以此时少一次swap, 可是i++ j++须要的 保持ij同步
事实证明未经过OJ測试的代码非常难保证正确性。leetcode setcolor题 就是上面的挂了,于是经过多种组合条件分析发现bug。单独处理1 interval空的情况
void sortColors(int a[], int n) {
int i=-1,j=-1;
for(int k=0;k<=n-1;k++)
{
if(a[k]==0)
{
if(i==j)//before are 2 or 0 2, swap one is only, two will error, also 0 swap once is ok, so that is no 1 interval would only swap once
{
i++;
swap(a[i],a[k]);
j++;
}
else
{
i++;
swap(a[i],a[k]);
j++;
swap(a[j],a[k]);
}
}
else if(a[k]==1)
{
j++;
swap(a[j],a[k]);
}
}
}
附上July版本号,前面 0 1区间 最后面2区间 1 2 之间没处理的
void sortColors(int a[], int n) {
int begin=0,end=n-1,current=0;
while(current<=end)
{
if(a[current]==0)
swap(a[begin],a[current]),begin++, current++;
else if(a[current]==1)
current++;
else if(a[current]==2)
swap(a[current],a[end]),end--; //current not move
}
}
这样的不用考虑特殊情况。比方 仅仅有2 和仅仅有0 2的区间的情况,事实上也是单向扫描过来的,仅仅是调整了未处理部分和 0 1 2 区间的顺序而已,由于指针从current+1, 到end处理了。一个
指针扫描的,还是单向扫描好。事实上也不是Hoart版啦,所以自己不用管Hoard版,坚持Lumoto版就能够了,sumous_t大神似乎也是的。
似乎另一种改进第一个版本号的思路。就是不swap,而是覆盖,像优化partition一样的
附上July博客 https://github.com/bolpigo/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.07.md
sumous_t 大神代码: https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/code/python/2.8:%20%E8%8D%B7%E5%85%B0%E5%9B%BD%E6%97%97%E9%97%AE%E9%A2%98.py
再附上sumous_t大神帮我改动后AC的代码,膜拜下大神,还是女博士哦:)
void sortColors(int a[], int n) {
int low=0,high=n-1;
int i=low-1,j=low-1;
for(int k=low;k<=high;k++)
{
if(a[k]==2) ;
else if(a[k]==1)
{
j++;
swap(a[j],a[k]);
}
else if(a[k]==0)
{
i++;j++;swap(a[j],a[k]);swap(a[j],a[i]);
}
}
July收集荷兰国旗问题之三路partition的更多相关文章
- 快速排序与荷兰国旗及Partition问题
快速排序与荷兰国旗及Partition问题 需求: 1.Partition过程 给定一个数组arr,和一个整数num.请把小于等于num的数放在数组的左边,大于num的数放在数组的右边. 要求额外空间 ...
- 算法笔记_051:荷兰国旗问题(Java)
目录 1 问题描述 2 解决方案 1 问题描述 现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右的球依次为红球.白球.蓝球.这个问题之所以叫荷兰国旗,是因为 ...
- 荷兰国旗问题、快排以及BFPRT算法
荷兰国旗问题 给定一个数组arr,和一个数num,请把小于num的数放数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边.要求额外空间复杂度O(1),时间复杂度O(N). 这个问题 ...
- 荷兰国旗 Flag of the Kingdom of the Netherlands
问题描述:现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右的球依次为红球.白球.蓝球.这个问题之所以叫做荷兰国旗,是因为将红白蓝三色的小球弄成条状物,并有序排列 ...
- ACM 荷兰国旗问题
荷兰国旗问题 时间限制:3000 ms | 内存限制:65535 KB 难度:1 描述 荷兰国旗有三横条块构成,自上到下的三条块颜色依次为红.白.蓝.现有若干由红.白.蓝三种颜色的条块序列,要 ...
- Coursera Algorithms week2 基础排序 练习测验: Dutch national flag 荷兰国旗问题算法
第二周课程的Elementray Sorts部分练习测验Interview Questions的第3题荷兰国旗问题很有意思.题目的原文描述如下: Dutch national flag. Given ...
- NYOJ_268_荷兰国旗问题
荷兰国旗问题 时间限制:3000 ms | 内存限制:65535 KB 难度:1 描写叙述 荷兰国旗有三横条块构成,自上到下的三条块颜色依次为红.白.蓝.现有若干由红.白.蓝三种颜色的条块序列.要 ...
- Java实现荷兰国旗问题
问题描述 现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右的球依次为红球.白球.蓝球.这个问题之所以叫荷兰国旗,是因为将红白蓝三色的小球弄成条状物,并有序排列后 ...
- java荷兰国旗问题
荷兰国旗包含三种颜色:红.白.蓝. 有三种颜色的球,算法的目标是将这三种球按颜色顺序正确地排列.它其实是三向切分快速排序的一种变种,在三向切分快速排序中,每次切分都将数组分成三个区间:小于切分元素.等 ...
随机推荐
- 【POJ2761】【fhq treap】A Simple Problem with Integers
Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...
- ZOJ3870 Team Formation
/** Author: Oliver ProblemId: ZOJ3870 Team Formation */ /* 思路 1.异或运算,使用^会爆,想到二进制: 2.我们可以试着从前往后模拟一位一位 ...
- PHP通过链接获取二进制数据的方法
function urltoblob($url){ $data = @file_get_contents($url); //如果file得不到数据,则给空值 if(!$data){ $data = & ...
- Redis 中的事务
Redis支持简单的事务 Redis与mysql事务的对比 Mysql Redis 开启 start transaction muitl 语句 普通sql 普通命令 失败 rollback 回滚 di ...
- jQuery height()、innerHeight()、outerHeight()函数的区别
参考: http://www.365mini.com/tech 函数 高度范围 jQuery版本 支持写操作 height() height 1.0+ 1.0+ innerHeight() heigh ...
- OBJC运行时方法替换(Method swizzling)
在上周associated objects一文中,我们开始探索Objective-C运行时的一些黑魔法.本周我们继续前行,来讨论可能是最受争议的运行时技术:method swizzling. Me ...
- oracle常见sql积累
select lower('HELLO') from dual;select lpad(100, 5, '*') from dual;select sysdate + 1 / 24 from dual ...
- 使用Echarts的五个步骤
_liuz 2015-07-22 09:35:53 参考网址:http://echarts.baidu.com/doc/start.html 一.制作一个图表容器<div id="m ...
- ios的Ping++支付接入步骤-b
1. Client 发送支付要素给 Server 2. Server 发送支付请求并将返回的支付凭据传给 Client 3. Client 调起支付控件完成支付 4. 渠道同步返回支付结果给 Clie ...
- eclipse 比较好的插件
tomcat 插件 egit github 插件 subeclipse 插件 Properties Editor Properties Editor 编辑java的属性文件,并可以自动存盘为Unico ...