来自《剑指offer》面试题4:替换空格。
牛客网AC地址:http://www.nowcoder.com/books/coding-interviews/4060ac7e3e404ad1a894ef3e17650423?rp=1
题目:请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
在牛客网上看到了给出的函数框架为,public String replaceSpace(StringBuffer str) {} ——这样,可以使用StringBuffer的话,题目的难度就减少了。
关注StringBuffer的两个函数:
int indexOf(String str, int fromIndex)
从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。
-
if the string argument occurs as a substring within this object, then the index of the first character of the first such substring is returned;
if it does not occur as a substring,
-1
is returned.
StringBuffer replace(int start, int end, String str)
使用给定 String 中的字符替换此序列的子字符串中的字符(参数:start包括,end不包括)
由此AC的Java代码为:
public class Solution {
public String replaceSpace(StringBuffer str) {
while (str.indexOf(" ") != -1) { // 找到空格出现的地方
int indexSpace = str.indexOf(" ");
str.replace(indexSpace, indexSpace + 1, "%20"); // 注意参数:Parameters: start The beginning index, inclusive.
// end The ending index, exclusive.
}
return str.toString();
}
}
测试代码为:
public class Main {
public static void main(String[] args) {
Solution testSolution = new Solution();
System.out.println("Waiting input:");
Scanner scanner = new Scanner(System.in);
String val = scanner.nextLine();
System.out.println("Replace space:" + testSolution.replaceSpace(new StringBuffer(val)));
}
}
运行结果:
这里补充,C的思路及代码。时间复杂度为O(n)
如果从前开始遍历字符串的话,每出现一个空格,就要进行替换,然后替换之后后面的字符串全部后移……这样进行操作的话,时间复杂度是O(n2)。
如果面试官要求时间复杂度为O(n),该怎么处理呢?
思路分析:
最终结果,该字符串长度增加了。由此,我们可以考虑从最终结果入手,指针从最终结果的末尾开始移动。
首先,先遍历一次字符串,统计出字符串中空格的个数,来计算替换之后字符串的总长度。(替换之后的字符串长度=原来的长度+2*空格数,这里是2*空格数,是因为原来的空格已经占有了一个长度,只需要在原来的基础上再增加两个长度就可以将%20插入进去)
然后,从字符串的后面开始复制和替换。准备两个指针,P1和P2,P1指向原始字符串的末尾,而P2指向替换之后的字符串的末尾。
P1向前移动,逐个把它指向的字符复制到P2指向的位置,直到碰到第一个空格为止。
碰到空格之后,P1向前移动1格,在P2之前插入字符串"%20",由于"%20"的长度为3,所以P2也要向前移动3格。
P1和P2的不断重复上述操作,直到P1和P2指向同一位置(此时所有的空格已经全部替换了)。
按照这样的思路,所有的字符都只复制(移动)了一次,由此这个算法的时间复杂度为O(n)。
这个思路书写的代码为:
// length为字符串数组string的总容量
void ReplaceSpace(char string[], int length) {
if (string == NULL || length <= 0)
return;
// originalLength为字符串string的实际长度
int orginalLength = 0;
int numOfSpace = 0;
int i = 0;
while (string[i] != '\0') { // 统计空格个数及字符串的原始长度
++originalLength;
if (string[i] == ' ')
++ numOfSpace;
++i;
}
// newLength为把空格替换为'%20'之后的长度
int newLength = originalLength + numOfSpace * 2;
if (newLength > length)
return;
// 定义两个指针,在字符串的后面进行复制和替换
int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while (indexOfOriginal >= 0 && indexOfNew > indexOfOriginal) {
if (string[indexOfOriginal] == ' ') { // 遇到空格
string[indexOfNew --] = '0';
string[indexOfNew --] = '2';
string[indexOfNew --] = '%';
}else {
string[indexOfNew --] = string[indexOfOriginal];
}
-- indexOfOriginal;
}
}
注:这段代码来自《剑指offer》P47.