剑指offer02-替换空格

253 阅读3分钟

替换空格

题目描述

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

思路1

  • 使用StringBuffer。

程序1(java)

    /**
     * code1
     *调用函数直接替换
     */
public class Solution {
    public String replaceSpace(StringBuffer str) {
        return str.toString().replace(" ", "%20");
    }
}
    /**
     * code2
     *从后往前
     */
public class Solution {
    public String replaceSpace(StringBuffer str) {
        if(str==null){
            return null;
        }
        int count=str.length();
    	for(int i=count-1;i>=0;i--){
            if(str.charAt(i)==' '){
                str. deleteCharAt(i);
                str.insert(i,"%20");
            }
        }
        return str.toString();
    }
}
    /**
     * code3
     *从前往后
     */
public class Solution {
    public String replaceSpace(String str) {
        if (str == null) {
            return null;
        }
        StringBuffer outputBuffer = new StringBuffer();
        for (int i = 0; i <str.length(); i++) {
            if (str.charAt(i) == ' ') {
                outputBuffer.append("%20");
            } else {
                outputBuffer.append(String.valueOf(str.charAt(i)));
            }
        }
        return new String(outputBuffer);
    }
}

思路2

  • 先统计空格数量,计算出替换后的字符串长度。采用两个索引p1和p2,初始时分别指向旧字符串和新字符串的最后一个字符的下标,然后开始从后先前遍历字符串(java字符串末尾没有‘\0’),逐个将p1指向的字符复制到p2指向的位置,直到碰到第一个空格为止。碰到第一个空格后,把p1向前移动一格,在p2之前插入字符串“%20”,由于“%20”的长度为3,同时也要把p2向前移动3格。如此重复,直至p1和p2指向同一位置。如下图所示。
(a). 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15
     w  e     a  r  e     h  a  p  p   y 
                                       p1              p2  
(b). 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15
     w  e     a  r  e                  h   a   p   p   y 
                       p1          p2
(c). 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15
     w  e     a  r  e        %  2  0   h   a   p   p   y 
                    p1    p2
(d). 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15
     w  e           a  r  e  %  2  0   h   a   p   p   y 
        p1       p2
(e). 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15
     w  e  %  2  0  a  r  e  %  2  0   h   a   p   p   y 
        p1
        p2

程序2(java)

    /**
     * code1
     * 牛客网
     * 时间复杂度O(n)
     */
public class Solution {
    public String replaceSpace(StringBuffer str) {
        if (str == null||str.length()<=0) {
            return str.toString();
        }
        int count = 0;
        for(int i=0;i<str.length();i++){
            if(str.charAt(i)==' '){
                count++;
            }
        }
        int p1=str.length()-1;
        int p2=count*2+str.length()-1;
        str.setLength(count*2+str.length());//将旧字符串的空间扩大
        while(p1>=0&&p1!=p2){
            if(str.charAt(p1)==' '){
                str.setCharAt(p2--,'0');
                str.setCharAt(p2--,'2');
                str.setCharAt(p2--,'%');
                p1--;
            }else{
                str.setCharAt(p2,str.charAt(p1--));
                p2--;
            }
        }
        return str.toString();
    }
}

补充

String、StringBuffer、StringBuilder:
  1. String : 是java.lang包中的immutable类,String里面所有的属性几乎也是final,由于它的不可变性,类似拼接,裁剪字符串等动作都会产生大量无用的中间对象。由于字符串操作在项目中很常见,所以对String的操作对项目的性能往往有很明显的影响。
  2. StringBuffer : 这个类是为了解决String拼接产生多余对象的问题而提供的一个类。StringBuffer保证了线程的安全,也带来了多余的开销。
  3. StringBuilder : StringBuilder的功能与StringBuffer一样。但是区别是StringBuilder没有处理线程安全,减少了开销。
区别
  • String 类型和StringBuffer的主要性能区别:String是不可变的对象, 因此在每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。
  • 使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
参考:
  1. Java:String、StringBuffer和StringBuilder的区别
  2. java中的StringBuffer和StringBuilder的用法,系统关键字之间的区别