劍指offer第二版面試題4:替換空格(JAVA版)

題目:請實現一個函數,把字符串中的每一個空格替換成「%20」。例如輸入「We are happy」,則輸出」We%20are%20happy」.面試

緣由:在網絡編程中,若是URL參數中含有特殊字符,如:空格、「#」等,可能致使服務器端沒法得到正確的參數值。咱們須要將這些特殊符號轉換成服務器識別的字符。轉換規則是在「%」後面跟上ASCII碼的兩位十六進制的表示。好比:空格的ASCII碼是32,即十六進制的0x20,所以空格被替換成「%20」。算法

 

時間複雜度爲O(n2)不足以拿到Offer編程

如今咱們考慮怎麼作替換操做。最直觀的作法是從頭至尾掃描字符串,每一次碰到空格字符的時候作替換。因爲是把1個字符替換成3個字符,咱們必須把空格後面的全部的字符都後移兩個字節,不然就有兩個字符被覆蓋了。數組

舉個例子,咱們從頭至尾把「We are happy」中的每個空格替換成」%20「。爲了形象起見,咱們能夠用一個表格來表示字符串,表格中的每一個格子表示一個字符。以下圖所示:服務器

 

咱們替換了第一個空格,這個字符串變成圖b中的內容,表格中灰色背景表示須要移動的字符。接着咱們替換第二個空格,替換以後的內容如圖c所示。同時咱們注意到用深灰色的背景標註」happy「部分被移動了兩次。網絡

假設字符的長度是n。對每一個空格字符,須要移動後面O(n)個字符,所以對含有O(n)個空格字符串而言總的時間效率是O(n2).app

當咱們把這種思路闡述給面試官後,他不會就此滿意,他將讓咱們尋找更快的方法。在前面的分析中,咱們發現數組中的不少字符都移動了不少次,能不能減小移動的次數呢?咱們換一種思路,把從前向後替換變爲從後向前替換。函數

考慮時間複雜度爲O(n)的解法,搞定Offer就靠它了spa

咱們先遍歷一次字符串,這樣就可以統計出字符串中空格的總數,並能夠計算出替換以後字符串的總長度。每替換一個空格,長度增長2,所以替換之後的字符串的長度等於原來的長度加上2乘以空格的數目,咱們仍是之前面的字符串」We are happy」爲例,「We are happy」這個字符串的長度是14,裏面有兩個空格,所以替換以後的字符串的長度爲18指針

咱們從字符串的後面開始複製和替換。首先準備兩個指針,P1和P2.   P1指向原始字符串的末尾,而P2指向替換以後的字符串的末尾。接下來咱們向前移動指針P1,逐個把它指向的字符複製到P2指向的位置,直到碰到第一個空格爲止。此時字符串包含以下圖b所示,灰色陰影的區域是作了字符拷貝的區域。碰到第一個空格以後,把P1向前移動一格,在P2以前插入字符串」%20「,因爲」%20「的長度爲3,同時也要把P2向前移動3格如圖所示。

咱們接着向前複製,直到碰到第二個空格(d)所示。和上一次同樣,咱們再把P1向前移動1格,並把P2向前移動3格插入」%20「(如圖e),此時P1,P2指向同一個位置,代表全部的空格都已經替換完畢。

從上面的分析咱們能夠看出,全部的字符都只複製一次,所以這個算法的時間效率是O(n),比第一個思路要快。

 

實現以下:(個人指針是從前面開始的)

public class Test4 {
    
    //將字符串中的空格變成%20
    public static String replaceAll(String str){
        //計算有多少個空格
        int count=0;
        char[] strArr = str.toCharArray();
        for(int i=0;i<strArr.length;i++){
            if(strArr[i]==' '){
                count++;
            }
        }
        //定義新數組
        char[] newArr=new char[strArr.length+count*2];
        //遍歷原數組,遇見空格就在新數組中寫入'%''2''0'
        //第幾個空格
        int num=0;
        for(int i=0,j=0;i<strArr.length;i++){
            //定義一個變量來存newArr的索引
            if(strArr[i]!=' '){
                newArr[j++]=strArr[i];
            }else{
                newArr[j++]='%';
                newArr[j++]='2';
                newArr[j++]='0';
            }
        }
        
        return new String(newArr);
    }
    
    public static void main(String[] args) {
        String str = replaceAll("hello world nihao a");
        System.out.println(str);
    }
}
相關文章
相關標籤/搜索