笔试题(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;

                    }

              }

       }

}

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值