剑指offer-chapter2-面试题4-替换空格(java)

题目: 替换空格

请实现一个函数,吧字符串中的每个空格替换成 “%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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章