给定一个字符数组,存储有R、G、B字符,将所有字符按照RGB顺序排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ssjhust123/article/details/8040283

这个题目隐约是在某个博客上看到过,后来书签掉了,一直找不到原文,所以只好自己写了一个解法,但愿没有出错。

题目描述

已知一个字符数组,其中存储有R、G、B字符,要求将所有的字符按照RGB的顺序进行排序。比如给定一个数组为char s[] = "RGBBRGGBGB",则排序后应该为RRGGGGBBBB。

 

分析

解法1)这个题目有点类似于快速排序中用到的划分数组的方法,但是这里有三个字符,因此需要调用划分方法两次,第一次以'B' 划分,第二次以'G'划分,这样两次划分后就可以将原来的字符数组划分成RGB顺序。这个方法比较自然,容易想到,代码如下。这个方法的缺点是需要遍历两遍数组。

/*划分函数*/
void partition(char *a, int lo, int hi, char t)
{
    int m = lo-1;
    for (int i=lo; i<=hi; i++) {
        if (a[i] != t) {
            swap(a, ++m, i);
        }
    }
}

/*主函数*/
void sort(char *a)
{ 
    int len = strlen(a);
    partition(a, 0, len-1, 'G');  //以G划分
    partition(a, 0, len-1, 'B');  //以B划分
}


解法2)其实还有一个只需要遍历一遍数组的方法,当然该方法虽然只遍历一遍数组,但是需要交换的次数并未减少。主要是设置两个变量r和g分别指示当前R和G字符所在的位置,遍历数组。

1)如果第i个位置为字符R,则与前面的指示变量r的后一个字符也就是++r处的字符交换,并++g,此时还需要判断交换后的i里面存储的字符是否是G,如果是G,则需要将其与g处的字符交换;

2)如果第i个位置为字符G,则将其与++g处的字符交换即可。++g指向的总是下一个应该交换G的位置,++r指向的是下一个需要交换R的位置。

3)如果第i个位置为字符B,则什么都不做,继续遍历。

void sort2(char *a, int lo, int hi, char *target)  
{
    int r, g; //++r和++g分别指向R和G交换的位置
    r = g = lo - 1;
    for (int i=lo; i<=hi; i++) {
        if (a[i] == target[0]) {  //target数组为"RG",因此target[0]='R',这是遇到R的情况
            swap(a, ++r, i);
            ++g;
            if (a[i] == target[1])
                swap(a, g, i);
        } else if (a[i] == target[1]) { //target[1]='G',这是遇到G的情况
            swap(a, ++g, i);
        } else {                   //遇到B的情况,什么都不做
            ;
        }
    }
}


 解法3)如果不考虑用交换的思想,可以直接统计RGB各个字符的个数,然后从头开始对数组重新赋值为RGB即可。那样简单多了,哈哈。但是如果换一个题,要求是对正数、负数、0按照一定顺序排列,那就必须用交换了。


 

 

没有更多推荐了,返回首页