[75].颜色分类

 


题目

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 012 分别表示红色、白色和蓝色。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

 


函数原型

C 的函数原型:

void sortColors(int* nums, int numsSize){}

 


边界判断

void sortColors(int* nums, int numsSize)
{
	if( nums == NULL || numsSize == 0 )
		return;
}

 


算法设计:快速排序

思想:先完成再优化,快排即可。

int cmp(const void *a,const void *b)
{
    return *(int *)a - *(int *)b;
}

void sortColors(int* nums, int numsSize)
{
	if( nums == NULL || numsSize == 0 )
		return;
	qsort(nums, numsSize, sizeof(int),cmp);
}
  • 时间复杂度: Θ ( n ∗ l o g n ) \Theta(n*logn) Θ(nlogn)
  • 空间复杂度: Θ ( n ) \Theta(n) Θ(n)
     

算法设计:计数排序

思路:使用计数排序的两趟扫描算法。

  • 迭代计算出 012 元素的个数,而后按照 012 的排序
  • 重写当前数组
void sortColors(int* nums, int numsSize)
{
	if( nums == NULL || numsSize == 0 )
		return;
		
    int red=0, white=0, blue=0, i;
    for(i=0; i<numsSize; i++)
        switch(nums[i]){
            case 0: red++; break;
            case 1: white++; break;
            case 2: blue++;
        }
        
    for(i=0; i<red; i++) nums[i]=0;
    for(i=red; i<red+white; i++) nums[i]=1;
    for(i=red+white; i<numsSize; i++) nums[i]=2;
}
  • 时间复杂度: Θ ( n ) \Theta(n) Θ(n)
  • 空间复杂度: Θ ( 1 ) \Theta(1) Θ(1)

 


算法设计:特征是三路分割,解法是使用三指针进行排序,根据当前指针所指的值进行交换

计数排序遍历了俩次,其实可用一次搞定。

思路:参考了快速排序的中位数思想,快速排序首先要确定一个待分割的元素做中间点 x x x,然后把所有小于等于 x x x 的元素放到 x x x 的左边,大于 x x x 的元素放到其右边。

目标是这样:


假设初始是这样:


定义三个指针:zeroitwo

  • 所有在子区间 [ 0 , z e r o ) [0, zero) [0,zero) 的元素都等于 0 0 0
  • 所有在子区间 [ z e r o , i ) [zero, i) [zero,i) 的元素都等于 1 1 1
  • 所有在子区间 [ t w o , l e n − 1 ] [two, len - 1] [two,len1] 的元素都等于 2 2 2

当遍历到某一元素 e 时:


e 有三种情况:

  • e = 1 e = 1 e=1

    i++ 即可,把 1 1 1 纳入到 [ z e r o , i ) [zero, i) [zero,i)

  • e = 2 e = 2 e=2

取出 two 前一个元素(暂时这个元素不知道是什么),与 2 交换即可。


而后 two--,把 2 2 2 纳入到 [ t w o , l e n − 1 ] [two, len - 1] [two,len1]


  • e = 0 e = 0 e=0

要找到 zero+1 这个元素,一定是 1 1 1

而后交换 zero+1i

而后 zero++,把 0 0 0 纳入到 [ 0 , z e r o ) [0, zero) [0,zero)

相应的 i++,看下一个元素:

不停的循环…就会排好序。

完整代码:

void swap(int * a, int * b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

void sortColors(int* nums, int numsSize){
    /* 三指针 一趟扫描 类似三路快排的partition */
    int * left = nums;
    int * cur = nums;
    int * right = nums + numsSize - 1;
    
    while(cur <= right){
        if(*cur == 0){
            swap(left, cur);
            cur ++;
            left ++;
        }else if(*cur == 1){
            cur ++;
        }else{
            swap(cur, right);
            right --;
        }
    }
    return nums;
}
  • 时间复杂度: Θ ( n ) \Theta(n) Θ(n)
  • 空间复杂度: Θ ( 1 ) \Theta(1) Θ(1)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值