题目: 替换空格
请实现一个函数,吧字符串中的每个空格替换成 “%20”。例如输入 “We are happy.” , 这输出“We%20arehappy.”。(不使用replace&insert方法和必须在原串中改变)
解题思路:
解法1:
思路: 复杂度O(n²),遍历所有字符并添加后移动后面的字符串(不推荐)。
如字符串“We are happy.”:
初始化:
W | e | a | r | e | h | a | p | p | y | . |
第一次移动(阴影代表需要移动的字符):
W | e | % | 2 | 0 | a | r | e | h | a | p | p | y | . |
第二次移动(深色配筋说明需要移动两次):
W | e | % | 2 | 0 | a | r | e | % | 2 | 0 | h | a | p | p | y | . |
由此思路可知时间复杂度O(n²),可写出代码:
// 复杂度O(n²),遍历所有字符并在添加后空格后面的字符串向后移动(不推荐)
public static StringBuilder replace1(StringBuilder target) {
if (target == null) {
return null;
}
for (int i = 0; i < target.length(); i++) {
if (target.charAt(i) == ' ') {
StringBuilder template = new StringBuilder(target);
//改变原来String的长度,增加2
target.setLength(target.length() + 2);
target.setCharAt(i, '%');
target.setCharAt(i + 1, '2');
target.setCharAt(i + 2, '0');
for (int j = i + 3; j < target.length(); j++) {
target.setCharAt(j, template.charAt(j - 2));
}
i += 2;
}
}
return target;
}
解法2:
思路:既然我们需要替换空格,那我们可不可以先对空格进行计数,然后拓展数组大小,再从后向前进行赋值呢?
W | e | a | r | e | h | a | p | p | y | . |
由字符串可知空格有2个,故需拓展4个大小,p1,p2分别为原来和拓展后的最后一个字符的位置:
W | e | a | r | e | h | a | p | p | y | . | ||||||
p1 | p2 |
将p1的下标的值赋给p2:
W | e | a | r | e | h | a | p | p | h | a | p | p | y | . | ||
p1 | p2 |
若是空格则赋 %20三个字符:
W | e | a | r | e | h | % | 2 | 0 | h | a | p | p | y | . | ||
p1 | p2 |
则到终点为:
W | e | % | 2 | 0 | a | r | e | % | 2 | 0 | h | a | p | p | y | . |
p1. p2 |
故可写出代码:
// 复杂度O(n),先记录空格个数在进行替换移动。
public static StringBuilder replace2(StringBuilder target) {
if (target == null) {
return null;
}
// 记录空格个数
int spaceNum = 0;
for (int i = 0; i < target.length(); i++) {
if (target.charAt(i) == ' ') {
spaceNum++;
}
}
// 以前下标
int oldIndex = target.length() - 1;
// 新的长度
int newLength = target.length() + spaceNum * 2;
// 新下标
int newIndex = newLength - 1;
target.setLength(newLength);
// 这里注意:
// 1.循环是从后往前,这样可以避免重复移动
// 2.判断条件:oldIndex < newIndex && newIndex >= 0 则无需全部遍历,若oldIndex<newIndex则代表所有空格已经被替换
for (; oldIndex < newIndex && newIndex >= 0; oldIndex--) {
if (target.charAt(oldIndex) == ' ') {
// 这里由于是从后向前循环,所以插入字符也应该倒插
target.setCharAt(newIndex--, '0');
target.setCharAt(newIndex--, '2');
target.setCharAt(newIndex--, '%');
} else {
target.setCharAt(newIndex--, target.charAt(oldIndex));
}
}
return target;
}
完整代码如下:
package problem4;
/**
* 题目: 替换空格
* 请实现一个函数,吧字符串中的每个空格替换成 “%20”。例如输入 “We are happy.” , 这输出“We%20arehappy.”。(不使用replace&insert方法和必须在原串中改变)
* Created by fengyuwusong on 2018/1/16 14:57.
*/
public class ReplaceSpance {
// 复杂度O(n²),遍历所有字符并添加后移动(不推荐)
public static StringBuilder replace1(StringBuilder target) {
if (target == null) {
return null;
}
for (int i = 0; i < target.length(); i++) {
if (target.charAt(i) == ' ') {
StringBuilder template = new StringBuilder(target);
//改变原来String的长度,增加2
target.setLength(target.length() + 2);
target.setCharAt(i, '%');
target.setCharAt(i + 1, '2');
target.setCharAt(i + 2, '0');
for (int j = i + 3; j < target.length(); j++) {
target.setCharAt(j, template.charAt(j - 2));
}
i += 2;
}
}
return target;
}
// 复杂度O(n),先记录空格个数在进行替换移动。
public static StringBuilder replace2(StringBuilder target) {
if (target == null) {
return null;
}
// 记录空格个数
int spaceNum = 0;
for (int i = 0; i < target.length(); i++) {
if (target.charAt(i) == ' ') {
spaceNum++;
}
}
// 以前下标
int oldIndex = target.length() - 1;
// 新的长度
int newLength = target.length() + spaceNum * 2;
// 新下标
int newIndex = newLength - 1;
target.setLength(newLength);
// 这里注意:
// 1.循环是从后往前,这样可以避免重复移动
// 2.判断条件:oldIndex < newIndex && newIndex >= 0 则无需全部遍历,若oldIndex<newIndex则代表所有空格已经被替换
for (; oldIndex < newIndex && newIndex >= 0; oldIndex--) {
if (target.charAt(oldIndex) == ' ') {
// 这里由于是从后向前循环,所以插入字符也应该倒插
target.setCharAt(newIndex--, '0');
target.setCharAt(newIndex--, '2');
target.setCharAt(newIndex--, '%');
} else {
target.setCharAt(newIndex--, target.charAt(oldIndex));
}
}
return target;
}
public static void main(String[] args) {
// 编写测试用例
// 第一个方法
// 开头空
System.out.println(replace1(new StringBuilder(" 2354")));
// 结尾空
System.out.println(replace1(new StringBuilder("2345 ")));
// 中间空
System.out.println(replace1(new StringBuilder("23 56")));
// 全部情况一起
System.out.println(replace1(new StringBuilder(" 2 34 ")));
// 空
System.out.println(replace1(null));
System.out.println(replace1(new StringBuilder("")));
// 单独空格
System.out.println(replace1(new StringBuilder(" ")));
// 连续空格
System.out.println(replace1(new StringBuilder(" ")));
System.out.println("----------------------");
// 第二个
// 开头空
System.out.println(replace2(new StringBuilder(" 2354")));
// 结尾空
System.out.println(replace2(new StringBuilder("2345 ")));
// 中间空
System.out.println(replace2(new StringBuilder("23 56")));
// 全部情况一起
System.out.println(replace2(new StringBuilder(" 2 34 ")));
// 空
System.out.println(replace2(null));
System.out.println(replace2(new StringBuilder("")));
// 单独空格
System.out.println(replace2(new StringBuilder(" ")));
// 连续空格
System.out.println(replace2(new StringBuilder(" ")));
}
}
相关问题:
有两个排序的数组A1和A2,内存在A1的末尾有足够的空余空间容纳A2。
请事先一个函数,把A2中的所有数字插入到A1中并且所有的数字是排序的。
解题思路:
解题思路:从尾到头比较A1和A2中的数字,并把较大的数字复制到A1的合适位置。
代码:
package problem4;
/**
* 相关问题:
* 有两个排序的数组A1和A2,内存在A1的末尾有足够的空余空间容纳A2。
* 请事先一个函数,把A2中的所有数字插入到A1中并且所有的数字是排序的。
* Created by fengyuwusong on 2018/1/16 23:00.
*/
public class Relative {
//解题思路:从尾到头比较A1和A2中的数字,并把较大的数字复制到A1的合适位置。
public static int[] merge(int[] a1, int[] a2, int a1Length, int a2Length) {
// a1的下标
int a1Index = a1Length - 1;
// a1的下标
int a2Index = a2Length - 1;
// 合并后总下标
int mergeIndex = a1Length + a2Length - 1;
// 判断长度是否足够
if (a1.length < mergeIndex + 1) {
System.out.println("a1长度不够");
return null;
}
// 进行从后向前循环比较并替换 优势:不用移动前面的数字
while (a1Index >= 0 && a2Index >= 0) {
if (a1[a1Index] >= a2[a2Index]) {
a1[mergeIndex] = a1[a1Index];
a1Index--;
mergeIndex--;
} else {
a1[mergeIndex] = a2[a2Index];
a2Index--;
mergeIndex--;
}
}
// 考虑情况a2比a1长度长,此时a1已经没有数字,则将a2剩余数字放在数组前面
// 无需考虑a1情况,因为a2本身已经在数组a1中
while (a2Index >= 0) {
a1[mergeIndex] = a2[a2Index];
a2Index--;
mergeIndex--;
}
return a1;
}
public static void show(int[] a1) {
if (a1 == null) {
return;
}
for (int i = 0; i < a1.length; i++) {
System.out.print(a1[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
int[] a1 = {1, 3, 6, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int[] a2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// a2比a1长
a1 = merge(a1, a2, 5, 9);
show(a1);
// a2比a1短
int[] a3 = {0, 1, 3, 6, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int[] a4 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
a1 = merge(a3, a4, 6, 3);
show(a1);
// a1长度不够
int[] a5 = {1, 3, 6, 9, 10};
int[] a6 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
a1 = merge(a5, a6, 5, 3);
show(a1);
}
}