博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面试题4:替换空格之发散思维
阅读量:7223 次
发布时间:2019-06-29

本文共 3757 字,大约阅读时间需要 12 分钟。

  题目:请实现一个函数,吧字符串的每个空格替换成“%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=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)                {                  //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

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

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

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

  答:睡觉了,明天再说

                                                2013年3月24日0:36:55

                                                  菜包子 于宿舍

 

 

转载于:https://www.cnblogs.com/CaiBaoZi/archive/2013/03/24/2977956.html

你可能感兴趣的文章
linux系统中如何查看日志(转)
查看>>
JavaScript的parseint()函数
查看>>
微信小程序 view 布局
查看>>
一步一步学Python(2) 连接多台主机执行脚本
查看>>
SUP (SAP Mobile SDK 2.2) 连接 Sybase SQL Anywhere sample 数据库
查看>>
流的压缩与解压缩函数
查看>>
Javascript 严格模式详解(转)
查看>>
AngularJS的Hello World
查看>>
日志池
查看>>
电子病历,到底是用BS还是CS
查看>>
Visual Studio (VSIX,项目模板 )制作
查看>>
两个人的荒岛
查看>>
机器学习经典书籍
查看>>
[nginx] nginx安装
查看>>
[转].NET 绘制 EAN13 (商品条码)
查看>>
【转】越狱的 iPhone、iPad 通过网站实现一键安装 ipa 格式的 APP 应用
查看>>
开发者的利器:Docker 理解与使用
查看>>
mybatis调用视图和存储过程
查看>>
Nested loops、Hash join、Sort merge join(三种连接类型原理、使用要点)
查看>>
RT-Thread的线程(任务)处理 rt_thread_create/rt_thread_init区别
查看>>