笔试题(1)

原题:
一个数组,里边存放三种球颜色值:红球为 'R',绿球为 'G ',蓝球为 'B ',
编程对该数组排序,使该数组最后的颜色排列如下:前边元素全部为 'R',中间元素全部为 'G',后边为 'B'

----------------------------------------------------------------------------------------------------------------------------------------------------

这道题在csdn论坛上一个03年发的帖子上有人讨论过,我这两天刚看到,集中看了集中解法,自己也给出了几种,这里一并说一下。(我在笔试中遇到过这道题目,同学去笔试时也有遇到,很值得探讨)

我在笔的时候:要求尽可能用swap,不允许分配连续的辅助空间。这里的解答就按照这个要求来:

方案①:我看到题目后立即想到的一种解法,时间复杂度较大,为0(n平方),空间复杂度O(1)。 用的冒泡排序。(这里给出这种不太好的解法,权当复习冒泡排序了)

void SortRGB(char* pData)

{

if(pData == NULL)

{

return;

}

int len = strlen(pData);

if(len<=1)

{

return;

}

char* temp ="RG";

int m = 0;

bool exchange;

int begin = 0;

while(begin<len)

{

exchange = false;

for(int j = len-1;j>=begin;j--)

{

if(pData[j] == temp[m])

{

if(j-1>=0)

swap(pData[j-1],pData[j]);

exchange = true;

}

}

begin++;

if(exchange == false)

{

m = 1;

}

}

}

上边的算法用的就是冒泡排序的思想,这导致时间复杂度很大。而真实的BubbleSort也不需要这么繁琐,只要两个嵌套的for循环就可以。

每一趟遍历要将一个元素冒到最前边。如果某一趟排序过后没有发生交换,则说明排序结束。

方案②:降低时间复杂度,使之为0(n),不过需要两趟遍历。

void SortRGB(char* pData)

{

if(pData == NULL)

{

return;

}

int len = strlen(pData);

if(len<=1)

{

return;

}

char* temp = "RG";

int ptr = 0;

int low = 0;

int high = len-1;

while(low<high && ptr<2)

{

while(pData[low] == temp[ptr])

{

low++;

}

while(pData[high] != temp[ptr])

{

high--;

}

if(low<high)

{

swap(pData[low],pData[high]);

}

else

{

high = len-1;

ptr++;

}

}

}

这个方案只需要对数组做两次遍历即可,时间复杂度已经大大降低。但是还有没有可以优化的空间而言呢?

分析一下上边两种方法发现:其有一个共同点就是:R和G的排序是分开进行的,亦即:先进行完R后,才会去进行B,有没有可能同时进行2个字母的排序呢?

后来跟同学讨论了下这个问题,大家都觉得有可能,杰哥给出了一种算法,只需要一趟就搞定。

方案③:

void sortRGB(char* str)

{

char* l=str;

int n=strlen(str);

//-----------------------------------------------

while(*l!='/0'&&*l=='R')

{

l++;

}

if(*l=='/0')

{

return;

}

//-----------------------------------------------

char* r = str+n-1;

while(*r=='B'&&r>=str)

{

r--;

}

if(r<0)

{

return;

}

//---------------------------------------------

char* p;

for(p=l; p<=r; p++)

{

while(*p!='G')

{

if(*p=='R')

{

swap(*p, *l++);

while(*l=='R')

l++;

p=max(p, l);

if(p>r) break;

}

if(*p=='B')

{

swap(*p, *r--);

while(*r=='B')

r--;

p=min(p, r);

if(p<l) break;

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值