5 替换空格(字符串的操作)(与lintcode 6、64题思想相同)

首先明确C++中每个字符串都以‘\0’作为结尾,例如字符串“12345”实际长度是6个字节,如果要复制该字符串,至少需要6个字节的数组。

面试题:

int main()
{
char str1[]="hello world";
char str2[]="hello world";
char*str3="hello world";

char*str4="hello world";

if(str1==str2)

printf("str1 and str2 are same.\n");

else printf("str1 and str2 are not same.\n");

if(str3==str4)

printf("str3 and str4 are same.\n");

else printf("str4 and str4 are not same.\n");

return 0;

}

输出:

解析:str1和str2是两个字符串数组,会被分配两个长度是12字节的空间,两个数组的初始地址不同,因此str1和str2也不同

str3和str4是两个指针,不需要为他们分配内存存储字符串的内容,只需要使他们指向“hello world”字符串的首地址即可。

“hello world”是一个字符串常量,其在内存中只有一个拷贝,因此str3和str4指向同一个地址。所以str3和str4是相同的。

 

题目描述

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

思路:

题目要求是:原来的一个空格被替换成‘%’、‘2’、‘0’这三个字符

有两种解法:

1、可以创建新的字符串,并在新的字符串上替换字符,这个很简单,新创建一个字符串数组,移动并替换字符即可。

时间复杂度:O(n)

空间复杂度:O(n)

2、在原来的字符数组上替换,则需要移动每个空格之后的字符

思路:为了使时间复杂度更低,我们必须减少字符移动的次数,最好遍历一次数组就全部移动完毕最好。

1、先遍历一遍字符串,统计空格的总数N,则原字符串长度需要增加2*N

2、开始从后往前遍历,用p1指向原来字符串长度的尾部,p2指向后来字符串长度的尾部

3、逐个将p1指向的字符复制到p2指向的空格中(图a)

4、当遇到空格时,p2向前移动3个空格,依次存储‘0’、‘2’、‘%’,p1向前移动一格

时间复杂度:O(n)

空间复杂度:O(1)

代码:

/*length 为字符串数组的总容量*/ 

class Solution {
public:
    string replaceSpace(string s) {
        if(s.size()==0) {
            return "";
        }
        
        int cnt = 0;
        for(int i = 0; i < s.size(); i++)
        {
            if(s[i] == ' ') {
                cnt++;
            }
        }
        
        int p = s.size()-1; //防止访问越界
        int q = p+cnt*2;
        //首先分配新空间
        s += string(cnt * 2,' ');
      
        while(p>=0 && p<=q)
        {
            if(s[p]==' ') {
                s[q--]='0';
                s[q--]='2';
                s[q--]='%';
                p--;
            } else {
                s[q--]=s[p--];
            }
        }
        
        return s;
    }
};

举一反三:
当合并两个数组(或者字符串)牵涉到元素移动问题时,如果从前往后移动需要复制并移动每个元素多次,那么可以考虑从后往前移动,以减少复制和移动的次数,提高效率。

相关题目:
有两个排序数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2。请实现一个函数,把A2中的所有数字插入A1中,并且所有的数字是排序的。

更好的思想是从尾到头比较A1和A2中的数字,并把较大的数字复制到A1中的合适位置

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值