首页 > 编程语言 >算法练习:两指针之三色排序

算法练习:两指针之三色排序

时间:2022-12-07 15:36:05浏览次数:40  
标签:p0 p1 int 之三 位置 指针 排序 nArray


问题描述

输入一个整型数组,每个元素在0~2之间,其中0,1,2分别代表红、白、蓝。现要求对数组进行排序,相同颜色的在一起,而且按红白蓝顺序先后排列。要求时间复杂度为O(n)。

 

问题分析

最容易想到的是排序,比如快排,归并,堆排等,但它们的时间复杂度为O(nlogn),与题意不符。

第二种想到的是计数排序,扫描一遍过去,分别记录0,1,2的个数,然后再对数组进行赋值。时间复杂度为O(2n),即O(n),满足条件。

还有一种方法,只需扫描一遍数组即可,其充分利用了元素只有3种的特性:在扫描数组的时候,使用首尾俩个指针,分别指示0、1与1、2边界。比如源数组为{2, 2, 0, 0, 1, 1  }。

 

第一步:首指针p0,尾指针p1,i标识当前扫描位置,当前位置值为2,需要将其交换至尾指针p1位置,p1要向前移动一位,p0、i位置不变。

算法练习:两指针之三色排序_数组

第二步:i位置值不为0、2,i要向后移动一位,p0、p1位置不变。

算法练习:两指针之三色排序_数组_02

第三步:i位置值为2,需要将其交换至尾指针p1位置,并且p1往前移动一位,i与p0位置不变。

算法练习:两指针之三色排序_时间复杂度_03

第四步:i位置不为0、2,i要向后移动一位,p0、p1位置不变。

算法练习:两指针之三色排序_时间复杂度_04

第五步:i位置值为0,需要将其交换至首指针p0位置,并且p0往后移动一位,i与p1位置不变。

算法练习:两指针之三色排序_数组_05

第六步:i位置不为0、2,i要向后移动一位,p0、p1位置不变。

算法练习:两指针之三色排序_ios_06

第七步:i位置值为0,需要将其交换至首指针p0位置,并且p0往后移动一位,i与p1位置不变。

 

算法练习:两指针之三色排序_ios_07

 

第八步:i位置不为0、2,i要向后移动一位,p0、p1位置不变。

算法练习:两指针之三色排序_ios_08

第九步:i位置超过p1位置了,结束。

 

实现代码

#include <iostream>

using namespace std;

void ThreeColorSort( int nArray[], int nCount )
{
int p0 = 0; //首指针
int p1 = nCount-1; //尾指针


int i = 1;
while( i <= p1 )
{
//当前值为2,与尾指针p1指向的值相互交换,p1向前移动一位
//i、p0位置不变
if ( nArray[i] == 2 )
{
int nTemp = nArray[i];
nArray[i] = nArray[p1];
nArray[p1--] = nTemp;
}
//当前值为0,与首指针p0指向的值相互交换,p0向后移动一位
//i、p0位置不变
else if ( nArray[i] == 0 && i > p0 )
{
int nTemp = nArray[i];
nArray[i] = nArray[p0];
nArray[p0++] = nTemp;
}
//i位置不为0、2,i要向后移动一位,p0、p1位置不变。
else
{
++i;
}
}
}


//书上的例子代码
void SortColors( int nArray[], int nCount )
{
int p0 = 0;
int p2 = nCount;
for( int i = 0; i < p2; ++i )
{
if ( nArray[i] == 0 )
{
int tmp = nArray[p0];
nArray[p0] = nArray[i];
nArray[i] = tmp;
++p0;
}
else if ( nArray[i] == 2 )
{
--p2;
int tmp = nArray[p2];
nArray[p2] = nArray[i];
nArray[i] = tmp;
--i;
}
}
}



int main()
{
//int nArray[] = { 2, 1, 0, 2, 0 };
//int nArray[] = { 0, 0, 1, 1, 2, 2 };
//int nArray[] = { 0 };
//int nArray[] = { 2, 0, 1 };
int nArray[] = { 2, 2, 0, 0, 1, 1 };
ThreeColorSort( nArray, _countof(nArray) );

//SortColors( nArray, _countof(nArray) );
for( int i = 0; i < _countof(nArray); ++i )
{
cout << nArray[i] << " ";
}
cout << endl;


return 0;
}




系列文章说明:
1.本系列文章[算法练习],仅仅是本人学习过程的一个记录以及自我激励,没有什么说教的意思。如果能给读者带来些许知识及感悟,那是我的荣幸。
2.本系列文章是本人学习陈东锋老师《进军硅谷,程序员面试揭秘》一书而写的一些心得体会,文章大多数观点均来自此书,特此说明!
3.文章之中,难免有诸多的错误与不足,欢迎读者批评指正,谢谢.

作者:山丘儿​


标签:p0,p1,int,之三,位置,指针,排序,nArray
From: https://blog.51cto.com/u_15905375/5919602

相关文章

  • sql分组,排序等一些函数的用法
    今天项目的两个地图数据有问题,经检查是由于数据重复造成的,需要去重,解决问题后把使用的相关函数汇总一下   group by是分组函数,partition by是分区函数(像sum()等......
  • 注意!!一定要谨慎使用c/c++原生指针
    主要是顶层逻辑中引用了一个指针,而在业务逻辑中将此指针删除了。这种在代码量很少的情况下,很容易被发现,但是代码量多了,逻辑多了的时候,想一下子定位到问题所在,就没那么容易了......
  • 字符集和排序规则
    字符集我们可以为MySQL服务器、数据库、表、字符类型的字段以及字符串常量指定一个字符集(CharacterSet)和排序规则(Collation)。其中,字符集决定了能够存储哪些字符,比如AS......
  • 三.双指针
    ​​面试题16.06.最小差​​classSolution:defsmallestDifference(self,a:List[int],b:List[int])->int:a.sort();b.sort()i=j=0......
  • 五. 排序算法
    1.定义:1.1原地排序和非原地排序def.原地排序算法使用恒定的的额外空间来产生输出。原地排序:选择排序,插入排序,希尔排序,快速排序,堆排序。非原地排序:归并排序,计数排序,基数排......
  • C++——引用&的功能及与指针*的区别
    C++——引用&的功能及与指针*的区别​​一、引用&的功能​​​​二、与指针*的区别​​​​三、真实案例​​​​参考资料​​一、引用&的功能用于函数传递参数,实现改变某个......
  • javaScript_01_按照key排序
     javaScript_01_按照key排序前言Object.keys()与Objetc.values()实现按key排序前言最近做一个小程序项目需要用到腾讯地图的api,在计算sig的时候需要将参数按照......
  • JavaScript中的中间排序算法
    英文|https://medium.com/@gianfranconuschese/intermediate-sorting-algorithms-in-javascript-4ec8b641b32翻译|web前端开发(ID:web_qdkf)最近,我介绍了一些使用JavaScri......
  • 集合工具类Collections指南,以及Comparable和Comparator排序详解
    ......
  • 二叉排序树
    通过二叉中序排序树能够实现升序排序。publicclassBinarySortTreeDemo2{publicstaticvoidmain(String[]args){intarr[]={1,2,56,43,3,2,46,34};......