面试题4:替换空格之发散思维

  题目:请实现一个函数,吧字符串的每个空格替换成“%20”,例如输入“we are happy”,则输入“we%20are%20happy ”。

  书中给出的代码是用C++实现的,时间复杂度是O(n),我的想法是用C#实现不指定字符串替换,一个字符串valueChars(char数组类型的),把字符串中的oldChars字符串,替换为newChars。注意valueChars,oldChars,newChars 三个的数据类型都是char [] 数组类型的

  开始写算法之前,想的算法的要求为:1,时间复杂度O(n) 2,常量的空间复杂度。实现过程中并不是这样的。

  首先强调一点在C#中和C++中char[]是有一些区别的.

  在C#中代码如下

            char[] str = new char[10];
            for (int i = 0; i < 10; i++) 
            {
                if (5 <= i&&i <= 6)
                    continue;
                str[i] = (char)(i+'0');
            }
            Console.WriteLine(str);

  请注意当str赋完值只收str的值,见下面图片

  

对于C#来说char[] 中的‘\0’并不是相当于C++中的字符串结束符,它可能不起作用,因此对于这点来说需要注意。

  为了使算法具有普适性,valueChars的实际长度(从第一个字符开始,遇到第一个'\0'字符时的长度)和它的占用的内存长度不同,其他的两个字符串也是这样。

  书中对于空格' '替换'%20',是从后面开始替换的,但是对于oldChars和newChars怎么办?最开始时我认为全部是从后开始替换就可以,但是当newChars的实际长度newActualLength(变量名nAlen)小于oldChars的实际长度(变量名oALen)时从后向前替换的问题时,已近替换好的字符串就有了一个需要向前移动的过程(自己脑补,不会画图)。这样显然不符合时间复杂度O(N)的要求,这个时候就需要向前开始移

  有缺陷的发散思维1:为了达到O(N)的时间复杂度(实际上不可能),当 nAlen<=oALen时,替换后字符串的实际长度缩小或者不变的,这个时候就需要向前开始从前面开始替换。当nAlen>oALen时,我们应该从字符串后面开始替换字符串。

  这样对应的算法是:

          1.给定的oldChars和newChars 求出oALen和nAlen。

          2.比较oALen和nAlen

          3.nAlen<=oALen 调用ReplaceFromHead函数,跳转5否则4

          4.调用ReplaceFromEnd函数

          5.结束

  按照这个思路,我就遇到了个各种各样的问题

  问题1.如何认定字符串匹配的问题?

  valueChars='aaabbbccc',oldChars='aa',newChars='d';出现了问题可以认为'aaa...' 和'aaa...'红色的部分是我要找的字符串oldChars,但是这两种情况替换下来结果完全不一样,因此采用最先匹配原则,即认为'aaa...'是应该的替换的字符串。

  答:采用最先匹配原则

  好了现在可以写从前向后匹配算法了,

  问题2.可以实现算法的时间复杂度为O(N)吗?

  答:不可能了,由于涉及到了字符串的匹配所以至少需要O(N*M)的时间复杂度,M是什么脑补,或者看下面的。

  首先需要找到哪里有oldChars,请看代码

在母串中寻找子串
在母串中找子串的原则

  bool eq=truewhile (index + oAlen <= vAlen)
            {
                eq = true;
                for (int k = 0; k < oAlen; k++) 
                {
                    if (value[index + k] != oldchars[k]) 
                    {
                        eq = false;
                        break;
                    }
                }
                if (eq)
                {
                  //do some thing
                    index = index + oAlen;
                }
                else 
                {
                    index++;
                }
            }

   知道M是什么了吧?里面的度something就是实现替换oldChars和newChars的替换,while的条件一个是为了减少比较次数,还有就是保证for循环中的value[index+k]不越界,出现异常。

  给出从前向后替换的全部代码,母字符串value,实际长度时vALen

从前向后替换字符串
  public void ReplaceFromHead(char[] value, int vAlen, char[] oldchars, int oAlen, char[] newChars, int nAlen) 
        {
            int newIndex=0, index = 0;
            bool eq = true;
            while (index + oAlen <= vAlen)
            {
                eq = true;
                for (int k = 0; k < oAlen; k++) 
                {
                    if (value[index + k] != oldchars[k]) 
                    {
                        eq = false;
                        break;
                    }
                }
                if (eq)
                {
                    for (int k = 0; k < nAlen; k++)
                    {
                        value[newIndex] = newChars[k];
                        newIndex++;
                    }
                    index = index + oAlen;
                }
                else 
                {
                    value[newIndex]=value[index];
                    newIndex++; 
                    index++;
                }
            }
            while (index<vAlen)
            {//把剩余的字符串移动到前面
                value[newIndex] = value[index];
                newIndex++;
                index++;
            }
            while(newIndex<value.Length)
            {
              value[newIndex] = '\0';
              newIndex++;
            }

        }

  newIndex代表移动后的value的指针,index扫描的是老的value的指针,当index扫描到新的oldChars时就替换,否则就把index指向的字符移到newindex的位置,然后一个while循环index后边的字符复制到index,完成字符串复制;在之后while保证新的value后面都是'\0',不会在输出是出错。

  我们可以按照相同的思路完成从 后向前移动的算法。

  问题3.真的可以这样实现从后向前移动的算法吗?为什么?

  答:睡觉了,明天再说

                                                2013年3月24日0:36:55

                                                  菜包子 于宿舍

 

 

posted on 2013-03-24 00:38  菜包子  阅读(333)  评论(0编辑  收藏  举报

导航