请实现一个函数,把字符串中的空格替换成%20,例如,输入“we are happy.”,输出“we%20are%20happy.”
将长度为1的空格替换为长度为3的“%20”,字符差的产度变长。如果允许我们开辟一个新的数组来存放替换空格后的字符串,那么这道题目就非常简 单。设置两个指针分别指向新旧字符串首元素,遍历原字符串,如果碰到空格就在新字符串上填入“%20”,否则就复制元字符串上的内容。
如果面试官要求只能在原先的字符串上操作,并且字符数组足够长以保存后替换后的字符,那么就得从别的方面着手。
方法一:
从前向后遍历,遇到空格就替换为%20,考虑可能会覆盖掉后面的字符,假设字符长度为n,每替换一个空格,就会需要向后移动O(n)个字符,因此就含有n个空格的字符串而言,总的时间效率是O(n^2)。这种方法显然不优。
方法二:
那我们换一种角度,从后先前遍历搜索,我们可以先遍历一遍数组,计算出空格的总数,并且可以由此计算出替换之后的字符串总长度,每替换一个空格,长度增加2,那么替换后的字符串总长度就等于原来的字符串长度加上2乘以空格数。
- 遍历求出空格数和字符串长度
- 求出替换后的字符串长度(原长+2*空格数)
- 设置两个指针p1,p2,分别指向原始字符串末尾和替换之后的字符串末尾
- 如果p1指向内容不为空格,那么将内容赋值给p2指向的位置,如果p1指向为空格,那么从p2开始赋值“02%”
直到p1==p2时表明字符串中的所有空格都已经替换完毕。
代码如下:
//把字数数组中的空格替换成%20
void replaceBlank(char s[],int len) {
//判断空指针,参数异常
if(s==null || len <= 0){
return ;
}
int i = 0;
int originalLen = 0;
int newLen = 0;
int blankCount = 0;
while(s[i]!='\0') {
originalLen ++;
if(s[i]==' ') {
++blankCount;
}
++i;
}
newLen = originalLen + 2*blankCount;
//如果新的长度大于了数组长度就会越界
if(newLen > len)
return ;
int indexOfOriginal = originalLen;//指向新数组的最后一个位置
int indexOfNew = newLen;//指向原数组的最后一个位置
while(indexOfOriginal >=0 && indexOfNew > indexOfOriginal) {
if(s[indexOfOriginal]== ' ') {
s[indexOfNew--] = '0';
s[indexOfNew--] = '2';
s[indexOfNew--] = '%';
}else {
s[indexOfNew--] = s[indexOfOriginal];
}
--indexOfOriginal;
}
}
@Test
public void testReplaceBlank() {
char s[] = {'w','e',' ','a','r','e',' ','h','a','p','p','y','\0',' ',' ',' ',' ',' '};
replaceBlank(s,18);
System.out.println(s);
}
输出结果:
we%20are%20happy
传字符串
public String replaceSpace(StringBuffer str) {
int len = str.length();
int blankNum = 0;
for(int i=0;i<len;i++) {
if(str.charAt(i)==' ') blankNum++;
}
for(int i=0;i<blankNum*2;i++) {
str.append(' ');
}
char a[] = str.toString().toCharArray();
int newLen = len+blankNum*2;
int indexOld = len - 1;
int indexNew = newLen - 1;
while(indexOld>=0 && indexOld<indexNew) {
if(a[indexOld]!=' ') {
a[indexNew--] = a[indexOld];
}else {
a[indexNew--] = '0';
a[indexNew--] = '2';
a[indexNew--] = '%';
}
indexOld--;
}
StringBuilder sb = new StringBuilder();
for(char c:a)
sb.append(c);
return sb.toString();
}
备注:(c++代码)
#include<iostream>
using namespace std;
//把字数数组中的空格替换成%20
void replaceBlank(char s[],int len) {
//判断空指针,参数异常
if(s==NULL || len <= 0){
return ;
}
int i = 0;
int originalLen = 0;
int newLen = 0;
int blankCount = 0;
while(s[i]!='\0') {
originalLen ++;
if(s[i]==' ') {
blankCount++;
}
i++;
}
newLen = originalLen + 2*blankCount;
int indexOfOriginal = originalLen;//指向新数组的最后一个位置
int indexOfNew = newLen;//指向原数组的最后一个位置
while(indexOfOriginal >=0 && indexOfNew > indexOfOriginal) {
if(s[indexOfOriginal]== ' ') {
s[indexOfNew--] = '0';
s[indexOfNew--] = '2';
s[indexOfNew--] = '%';
}else {
s[indexOfNew--] = s[indexOfOriginal];
}
indexOfOriginal--;
}
}
void main() {
//char s[] = {'w','e',' ','a','r','e',' ','h','a','p','p','y'};
char s[20] = "we are happy." ;
replaceBlank(s,12);
cout<<s;
}
相关问题:
`有两个排序的数组A1和A2,内存在A1的末尾有足够的空间容纳A2,请实现一个函数,把A2中的所有数字插入到A1中,并保持有序。`
解法:和前面一样,很多人首先想到的办法是在A1中从头到尾复制数字,这样出现多次复制同一个数字的情况。更好的办法是从尾到头比较A1和A2的数字,并把较大的数字复制到A1中合适的位置。
代码:
#include<iostream>
using namespace std;
void a1_a2(int a1[],int a2[],int a1_len) {
if(a1==NULL || a2==NULL || a1_len <=0)
return ;
int i = 0;
int len1=0,len2=0;
//遍历连个数组,求出字符长度
while(a1[i]!='\0'){
len1++;
i++;
}
i = 0;
while(a2[i]!='\0'){
len2++;
i++;
}
int newLen = len1 + len2;
if(newLen > a1_len) {
//越界
return;
}
int indexOfNew = newLen - 1;
int indexOfA1 = len1-1;
int indexOfA2 = len2-1;
while(indexOfA1>=0 && indexOfA2>=0) {
if(a1[indexOfA1] <= a2[indexOfA2])
a1[indexOfNew--] = a2[indexOfA2--];
else
a1[indexOfNew--] = a1[indexOfA1--];
}
while(indexOfA1 >= 0) {
a1[indexOfNew--] = a1[indexOfA1--];
}
while(indexOfA2 >= 0) {
a1[indexOfNew--] = a2[indexOfA2--];
}
}
void main(){
int a1[10] = {3,5,8,9};
int a2[7] = {2,6,7,10};
a1_a2(a1,a2,10);
int i = 0;
while(a1[i]!='\0') {
cout<<a1[i];
i++;
}
cout<<endl;
}
本文介绍了一种在原地将字符串中的空格替换为%20的方法,避免使用额外空间。通过两次遍历,先计算空格数量并确定新字符串长度,再从后向前逐个替换,确保效率为O(n)。
1149

被折叠的 条评论
为什么被折叠?



