持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
题目
实现一个函数可以将字符串中每个空格替换为"%20"。举例输入"We are Family",进过函数处理后输出"We%20are%20Family"。
解题思路
- 每个空格替换为%20等同于1个字符替换成3个字符。
- 字符串总长度变长了。
若使用已有String替换方法实现本题解法是简单的,利用replace(a,b)将a替换成b即可。但先不考虑采用api解题方式自行实现方法来满足题目要求。
StringBuilder res = new StringBuilder();
for(Character c : s.toCharArray())
{
if(c == ' ') res.append("%20");
else res.append(c);
}
return res.toString();
PS:面向对象开发真香~
Char遍历法
char是字符类型,String是字符串类型;char是基本类型,String是类;char用''表示,String用""表示。在Java中通过遍历String字符串每个字符来找到空格并填写新字符来实现。
- 官方解题方式
int length = s.length();
char[] array = new char[length * 3];
int size = 0;
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
if (c == ' ') {
array[size++] = '%';
array[size++] = '2';
array[size++] = '0';
} else {
array[size++] = c;
}
}
String newStr = new String(array, 0, size);
return newStr;
为了满足所有空格需求对整体字符串做扩展满足全为空格的情况,缺点就是占用空间大了。
- 自写解题方式
int length = s.length(); //总长度
int size = 0; // 空格数
for(int i = 0; i < s.length();i++){
if(s.charAt(i)==' '){
size++;
}
}
char[] newChar = new char[length + size * 2]; //新字符串长度
int p = 0;
for(int i = 0; i < s.length();i++){
if(s.charAt(i)==' '){
newChar[p++] = '%';
newChar[p++] = '2';
newChar[p++] = '0';
}else{
newChar[p++] = s.charAt(i);
}
}
return new String(newChar);
对以上解法做了小小优化,先遍历一次字符串得到空格数,根据空格数再扩展实际字符串长度空间大小。
指针法
- 同理先遍历字符串获取空格数,每个空格长度加2
- 准备i,j两个指针分别指向原字符串末尾和新字符串末尾。
- 移动i指针逐个字符复制到新字符串中,直到碰到空格。
- i遇到空格时j中插入%20,j指针往前移动3位,i再向前一位。
- 直到i和j指向同一位置表示空格替换结束。
int count = 0; // 统计空格的个数
int oldLength = s.size();
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') {
count++;
}
}
s.resize(s.size() + count * 2);// 新长度
int length = s.size();
// 从后往前替换空格为"%20"
for (int i = length - 1, j = oldLength - 1; j < i; i--, j--) {
if (s[j] != ' ') {
s[i] = s[j];
} else {
s[i] = '0';
s[i - 1] = '2';
s[i - 2] = '%';
i -= 2;
}
}
return s;
原生算法(骚操作)
return s.replace(" ", "%20");
在Android中replace方法实现底层有Native来完成算法。
public String replace(char oldChar, char newChar) {
// BEGIN Android-changed: Replace with implementation using native doReplace method.
if (oldChar != newChar) {
final int len = length();
for (int i = 0; i < len; ++i) {
if (charAt(i) == oldChar) {
return doReplace(oldChar, newChar);
}
}
}
// END Android-changed: Replace with implementation using native doReplace method.
return this;
}
@FastNative
private native String doReplace(char oldChar, char newChar);
在JavaSDK中String的替换方法内部实现有正则参与。
| replace | replaceAll |
|---|---|
| 该副本将字符串中所有出现的target子字符串都替换成replacement。 | 改副本将字符串中所有出现的满足正则表达式regex的子字符串都替换成replacement。 |
但是两者性能上存在较大差异,相较而言replace比replaceAll耗时更短效率更高(主要是正则处理会慢些)。在简单替换字符串方式上尽量采用replace实现,对于复杂需要使用正则时才推荐使用replaceAll。