剑指Offer

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

解题思路

不使用新空间-基础版
不使用新空间意味着,只可以在原字符串上修改。最普通的方法就是直接从头到尾遍历,找到空格进行替换。
PS :插入的字符串和原字符的数量不同,导致新的字符串需要后移(这里的移动次数很关键)

不使用新空间-升级版
首先计算出空格数量。由此可以判断出需要的空间数。
然后从后向前开始向右移动,遇到空格进行替换。直到结束。
从后向前进行插入替换,移动次数大大降低。
PS:需要考虑到空格移动的情况

效率比较
从前向后
we are happy
第1次从前向后移动的时候需要 移动 are happy
第2次从前向后移动的时候需要 移动 happy
happy移动2次

从后向前
第1次从后向前移动的时候需要 移动 happy
第2次从后向前移动的时候需要 移动 are
由上面可见 从后向前的效率问题

使用新空间的话比较简单
拆分+合并即可

代码实现

基础版

public String replaceSpace(StringBuffer str) {
if(str == null) {
return "";
}
int length = str.length();
int asc = 32; //空格ASC
for (int i = 0; i < length; i++){
char c = str.charAt(i);
//存在空格
if (c == asc){
//右面的全部右移2位数
str.setLength(str.length()+2);
System.out.println(str.length());
for (int j = str.length()-1; j-1 > i; j--) {
str.setCharAt(j,str.charAt(j-2));
}
char char01 = '%';
char char02 = '2';
char char03 = '0';
str.setCharAt(i,char01);
str.setCharAt(i+1,char02);
str.setCharAt(i+2,char03);
}
}
return str.toString();
}

升级版

public static String replaceSpace(StringBuffer str) {
if(str == null) {
return "";
}
int num = 0;
int asc = 32; //空格ASC
for (int i = 0; i < str.length(); i++){
if (asc == str.charAt(i)){
num++;
}
}
str.setLength(str.length()+2*num);
int flag = str.length()-1;
for (int i = str.length()-1; i-1 > 0; i--) {
if (num == 0) {
break;
}
//移动
str.setCharAt(i,str.charAt(i-2*num));
//替换
if (str.charAt(i-2*num) == asc) {
str.setCharAt(i,'0');
str.setCharAt(i-1,'2');
str.setCharAt(i-2,'%');
//标记此下次需要移动的位置
num--;
i -= 2;
}
}
return str.toString();
}