面试题5:替换空格
题目描述
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
第三次做; 延长原始StringBuffer的长度, 时间复杂度O(N), 空间复杂度最差是O(N), 比如说原始字符串全是空格; 核心: 长度扩展多少? 不是3spaceCount, 要考虑到原始的空格, 每个空格对应两个新的位置, 所以一共扩展2spaceCount的长度
public class Solution {
public String replaceSpace(StringBuffer str) {
//input check
if(str==null)
return "";
if(str.length()==0)
return str.toString();
//
int spaceCount = 0, n = str.length();
for(int i=0; i<n; i++){
if(str.charAt(i)==' ')
spaceCount++;
}
//扩展长度; 核心: 长度增加多少? 不是
str.setLength(n+2*spaceCount);
//从后往前更新str
int left = n-1, right = str.length()-1;
while(left>=0 && right>=0){
char ch = str.charAt(left);
if(ch != ' '){
str.setCharAt(right--, ch);
left--;
}
else{
str.setCharAt(right--, '0'); //是char,不是String
str.setCharAt(right--, '2');
str.setCharAt(right--,'%');
left--;
}
}
return str.toString();
}
}
第三次做; 创建一个新的StringBuilder, 时间复杂度O(N), 空间复杂度O(N)
public class Solution {
public String replaceSpace(StringBuffer str) {
//input check
if(str==null || str.length()==0)
return str.toString();
//从后往前
StringBuilder sb = new StringBuilder();
for(int i=0; i<str.length(); i++){
char ch = str.charAt(i);
if(ch==' ')
sb.append("%20");
else
sb.append(ch);
}
return sb.toString();
}
}
思路
- 先明确需求.如果实在原来的字符串上进行替换,就有可能覆盖修改在该字符串后面的内存; 如果是创建新的字符串并在新的字符串上进行替换,那么就可以自己分配足够多的的内存
- 需求: 返回一个新字符串
- 创建一个新StringBuffer, 逐个复制, 遇到空格时做特殊处理, 用if else就可以了
- 期初犯错了,StringBuffer(newLen)并不会创建一个长为newLen的字符串,而是创建一个长为0的字符串
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
反思
选择从前往后复制还是从后往前复制,要根据具体情况决定. 本题可以确定新字符串的长度, 所以从前往后或者从后往前都行
第二次做, 直接在原输入上操作; 注意setLength的大小; setCharAt(index, char); 一个指针倒序遍历原输入, 另一个指针倒序遍历改变长度后的原输入
public class Solution {
public String replaceSpace(StringBuffer str) {
if(str==null || str.length()==0)
return str.toString();
//
//直接在原输入上进行修改
int spaceCount = 0;
for(int i=0; i<str.length(); i++){
if(str.charAt(i)==' ')
spaceCount++;
}
int i = str.length()-1;
//set new length
str.setLength(str.length()+spaceCount*2);
//modify reversely
for(int j=str.length()-1; j>=0&&i>=0; j--,i--){
if(str.charAt(i)==' '){
str.setCharAt(j--,'0');
str.setCharAt(j--,'2');
str.setCharAt(j, '%');
}
else
str.setCharAt(j, str.charAt(i));
}
return str.toString();
}
}
空间复杂度O(N)的解法
public class Solution {
public String replaceSpace(StringBuffer str) {
//input check
if(str==null) return null;
//
int len = str.length();
StringBuilder sb = new StringBuilder();
for(int i=0; i<len; i++){
if(str.charAt(i) == ' ')
sb.append("%20");
else
sb.append(str.charAt(i));
}
return sb.toString();
}
}
空间复杂度O(1)的解法
public class Solution {
public String replaceSpace(StringBuffer str) {
//input check
if(str==null)return null;
//
int len = str.length();
int spaceCount = 0;
for(int i=0; i<len; i++)
if(str.charAt(i)==' ')
spaceCount++;
int newLen = len + 2*spaceCount;
//调整str长度
str.setLength(newLen);
//从后往前调整str中各个char的位置
int newI=newLen-1, oldI=len-1;
//循环时:仍有空格位处理,没有空格时newI==oldI
while(newI>oldI){
if(str.charAt(oldI)==' '){
str.setCharAt(newI--, '0');
str.setCharAt(newI--, '2');
str.setCharAt(newI--, '%');
}
else{
str.setCharAt(newI--,str.charAt(oldI));
}
oldI--;
}
return str.toString();
}
}
for 循环版本; 要适应for循环中有两个条件的写法
public class Solution {
public String replaceSpace(StringBuffer str) {
//input check
if(str==null)return null;
//
int len = str.length();
int spaceCount = 0;
for(int i=0; i<len; i++)
if(str.charAt(i)==' ')
spaceCount++;
int newLen = len + 2*spaceCount;
//调整str长度
str.setLength(newLen);
//从后往前调整str中各个char的位置
int newI=newLen-1, oldI=len-1;
//循环时:仍有空格位处理,没有空格时newI==oldI
for(; newI>oldI; oldI--){
if(str.charAt(oldI)==' '){
str.setCharAt(newI--, '0');
str.setCharAt(newI--, '2');
str.setCharAt(newI--, '%');
}
else{
str.setCharAt(newI--,str.charAt(oldI));
}
}
return str.toString();
}
}