C++_字符串空格替换/《剑指offer.2》

网上的正确代码很多,我在这里只是想记录一下自己解题中的所有问题,希望能通过总结与反思使自己能稍稍有所提高。

题目:将一个字符串中的每个空格替换成“%20”.例如:we are happy.-----> we%20are%20happy.

阶段一:基础知识回顾

因为真的好久没有编代码了,所以想自己动手把涉及到的基础知识补回来,而不是看一眼别人的代码知道这里就是这个样子。
1、字符串长度:
	类模板传入的参数有长度,在定义不同字符串和字符数组的时候,具体的长度以及函数用法会有所不同,可参考
	博客:https://blog.csdn.net/z_qifa/article/details/77744482(sizeof()、strlen()、length()、size()详解和区别)
2、用指针的时候,内存地址变化,以及返回的内存地址。
	 这里是因为开始在Vs上可以编译通过,但是牛客网上不通过,查看论坛的时候看到有人这样说了一下,
	 然后就进行了单步调试以及内存检测,发现str地址真的发生了变化

阶段二:摸清题目真实意图

根据何海涛《剑指offer》
	1、内存覆盖:若直接把空格替换成 %20,那字符串总长度会变长,会覆盖在该字符串后面的内存。
	2、时间复杂度:
 	   ①从前往后替换的话,在遇到第一个空格时,后面的部分需要整体往后挪动两格,给 ‘2’‘0’ 腾出来位置,在遇到第二个空格的时候,这后面的整体同样需要再往后挪动两格。
    	由此可知,对于长度为n的字符串,如果有n个空格,那么时间复杂度就是O(n*n).
	  ②从后往前替换。 先正序遍历字符串,统计出空格的数量,得到替换后字符串的总长度;然后定义两个指针p1,p2,
	    分别指向原字符串末尾、替换后字符串末尾;开始从后向前遍历,如果遇到空格,p2-- = 0;p2-- = 2;p2-- = %;
	    即p2指针向前移动三格,同时插入‘%20’,如果没有遇到空格,把p1的值赋值给p2--即可;p1在每次遍历的时候向前移动一格;当p1和p2指向同一个位置的时候,证明所有空格替换完毕。
	    上述方法,所有的字符只用复制一次(移动),时间效率是O(n).

阶段三:实现算法调试Bug阶段

1、判断相等 语句
		if (str[i] == ' ')     出错:    写成 = ,这是好低级的错误,会出现中断错误,切记不可再错!
2、str[i]  和  *str   都是可以的
		根据前面分析 ,需要建立两个指向末尾的指针,有两种方法:
		2.1、指针指向字符串末尾
		char *pStr1 = str + Originallength;     // 字符指针指向原始字符串的末尾
		char *pStr2 = str + len;                      // 字符指针指向替换后字符串的末尾
		while (pStr1 != pStr2)                      // 替换结束的条件
		{
			if (*pStr1 == ' ')
			{
				*pStr2-- = '0';
				*pStr2-- = '2';
				*pStr2-- = '%';
			}
			else
			{
				*pStr2-- = *pStr1;
			}
			--pStr1;
		}
		2.2、用字符数组,不过索引改成新的长度
		int indexOfOriginal = Originallength;        
		int indexOfNew = newLength;
		while (indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
		{
			if (str[indexOfOriginal] == ' ')
			{
				str[indexOfNew--] = '0';
				str[indexOfNew--] = '2';
				str[indexOfNew--] = '%';
			}
			else
			{
				str[indexOfNew--] = str[indexOfOriginal];
			}		
			--indexOfOriginal;
		}
3、可以看子程序中返回的str地址:
	printf("%p\n",&str[0]);
	传入的字符串首地址:0117FBDC        //原字符串所分配内存地址
	新建字符串-地址:0117FAD4	      //新建一个字符串,进行赋值替换操作,返回地址不对  
	指针型——地址:0117FBDC             // 返回地址和原内存分配的地址一致
	字符数组——地址:0117FBDC

所有正确代码:

class Solution2  //先查出来一共有多少空格,然后从后往前替换
{
public:
	void replaceSpace(char *str, int length)
	{
		//边界检查1:判断字符串是否为空
		if (str == NULL||length<=0)
			return;
		//遍历字符串,统计空格数、替换前字符个数、替换后字符个数
		int CountOfBlanks = 0;    //空格个数
		int Originallength = 0;   //替换前字符个数
		int newLength = 0;              //替换后字符个数
		for (int i = 0; str[i] != '\0'; ++i)
		{
			Originallength++;
			if (str[i] == ' ')
				++CountOfBlanks;
		}
		newLength = Originallength + 2 * CountOfBlanks;
		//边界检查2:判断字符数组是否越界
		if (newLength + 1 > length)
			return;
		//替换空格
		int indexOfOriginal = Originallength;
		int indexOfNew = newLength;
		while (indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
		{
			if (str[indexOfOriginal] == ' ')
			{
				str[indexOfNew--] = '0';
				str[indexOfNew--] = '2';
				str[indexOfNew--] = '%';
			}
			else
			{
				str[indexOfNew--] = str[indexOfOriginal];
			}		
			--indexOfOriginal;
		}
		cout << str << endl;
		printf("字符数组——地址:%p\n\n", &str[0]);
	}
};
class Solution3 {
public:
	// 指向字符数组的字符指针str,字符数组长度length
	void replaceSpace(char *str, int length) {

		// 边界检查1:判断字符数组是否为空
		if (str == NULL)
			return;
		// 遍历字符串,统计空格个数、替换前字符个数、替换后字符个数
		int CountOfBlanks = 0; // 空格个数
		int Originallength = 0;// 替换前字符个数
		int len = 0;           // 替换后字符个数
		for (int i = 0; str[i] != '\0'; ++i)
		{
			Originallength++;
			if (str[i] == ' ')
				++CountOfBlanks;
		}
		len = Originallength + 2 * CountOfBlanks;
		// 边界检查2:判断字符数组是否越界
		if (len + 1>length)
			return;
		// 替换空格
		char *pStr1 = str + Originallength;// 字符指针指向原始字符串的末尾
		char *pStr2 = str + len;           // 字符指针指向替换后字符串的末尾
		while (pStr1 != pStr2)         // 替换结束的条件
		{
			if (*pStr1 == ' ')
			{
				*pStr2-- = '0';
				*pStr2-- = '2';
				*pStr2-- = '%';
			}
			else
			{
				*pStr2-- = *pStr1;
			}
			--pStr1;
		}
		cout << str << endl;
		printf("指针型——地址:%p\n\n", &str[0]);
	}
};

int main()
{
	Solution2 B2;
	Solution3 B3;
	const int length = 100;
	char str[length] = "We are happy.";
	printf("传入的字符串首地址:%p\n\n",&str[0]);//地址用十六进制表示
	B2.replaceSpace(str, length);
	B3.replaceSpace(str, length);
	system("pause");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值