劍指Offer(Java)-替換空格

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

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

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

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

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

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

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

以下代碼:函數

package cglib;spa

public class SingletonClass {指針

    public static void main(String args[]){
        String s="We are happy.";
        System.out.println(replaceBlank(s));
        }
        public static String replaceBlank(String input){
        if(input==null)
        return null;
        StringBuffer outputBuffer=new StringBuffer();
        for(int i=0;i<input.length();i++){
        if(input.charAt(i)==' '){
        outputBuffer.append("%");
        outputBuffer.append("2");
        outputBuffer.append("0");
        }else {
        outputBuffer.append(String.valueOf(input.charAt(i)));
        }
        }
        return new String(outputBuffer);
        }
}


輸出爲:

We%20are%20happy.

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

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

 

咱們先遍歷一次字符串,這樣就可以統計出字符串中空格的綜述,並能夠計算出替換以後字符串的總的長度。每替換一個空格,長度增長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),比第一個思路要快。

實現以下:

package cglib;

public class SingletonClass {

     //計算字符串中包含的空格個數  
    public static int getBlankNum(String testString){  
        int count = 0 ;  
        for(int i = 0;i<testString.length();i++){  
            String tempString = String.valueOf(testString.charAt(i));  
            if(tempString.equals(" ")){  
                count++;  
            }  
        }  
        return count;  
    }  
    //打印char[] 數組  
    public static void printArray(char[] testArray){
        System.out.println("開始打印數組");
        for(char i :testArray){  
            System.out.print(i);  
        }  
        System.out.println();  
    }  
    //將字符串空格轉化爲20%  
    public static void replaceAllBlank(String testString){  
        if(testString == null || testString.length() <= 0){  
            return;  
        }  
        //字符數組初始長度  
        int length = testString.length();
        System.out.println("字符串原始長度:"+length);
        //字符數組增長長度後  
        int newLength = testString.length()+ getBlankNum(testString)*2;  
        System.out.println("字符串增長後的長度:"+newLength);
        char[] tempArray = new char[newLength];
        System.out.println("數組:"+tempArray);
        System.arraycopy(testString.toCharArray(), 0, tempArray, 0, testString.toCharArray().length);  
        System.out.println("字符:"+testString.toCharArray());
        System.out.println("長度:"+testString.toCharArray().length);
        int indexofOriginal = length - 1;  
        int indexofNew = newLength -1;  
        System.out.println("未替換空格時的字符串:");  
        printArray(testString.toCharArray());
    
        while(indexofOriginal >=0 && indexofOriginal != indexofNew){
            System.out.println("indexofOriginal:"+indexofOriginal);//原始數組最後一位
            System.out.println("indexofNew:"+indexofNew);//替換數組最後一位
            System.out.println("tempArray[indexofOriginal]:"+tempArray[indexofOriginal]);
            if(tempArray[indexofOriginal]==' '){
                System.out.println("出現空格,替換");
                tempArray[indexofNew--]='0';
                System.out.println("替換第一個字符後:tempArray[indexofNew]="+tempArray[indexofNew]);
                System.out.println("替換第一個字符後:indexofNew="+indexofNew);
                tempArray[indexofNew--]='2';
                System.out.println("替換第二個字符後:tempArray[indexofNew]="+tempArray[indexofNew]);
                System.out.println("替換第二個字符後:indexofNew="+indexofNew);
                tempArray[indexofNew--]='%';
                System.out.println("替換第三個字符後:tempArray[indexofNew]="+tempArray[indexofNew]);
                System.out.println("替換第三個字符後:indexofNew="+indexofNew);
                
            }else{
                System.out.println("沒有空格數組裏面自減前:indexofNew="+indexofNew);
                tempArray[indexofNew--]= tempArray[indexofOriginal];
                System.out.println("沒有空格:tempArray[indexofOriginal]="+tempArray[indexofOriginal]);
                System.out.println("沒有空格賦值後:tempArray[indexofNew]="+tempArray[indexofNew]);
                System.out.println("沒有空格數組裏面自減後:indexofNew="+indexofNew);
            }  
            System.out.println("indexofOriginal自減前:"+indexofOriginal);
            indexofOriginal--;
            System.out.println("indexofOriginal自減後:"+indexofOriginal);
        }  
        System.out.println("替換空格後的字符串:");  
        printArray(tempArray);  
    }  
    public static void main(String[] args){  
        String str = "We are happy";  
        replaceAllBlank(str);  
    }  
}


輸出:

字符串原始長度:12
字符串增長後的長度:16
數組:[C@139a55
字符:[C@1db9742
長度:12
未替換空格時的字符串:
開始打印數組
We are happy
indexofOriginal:11
indexofNew:15
tempArray[indexofOriginal]:y
沒有空格數組裏面自減前:indexofNew=15
沒有空格:tempArray[indexofOriginal]=y
沒有空格賦值後:tempArray[indexofNew]=

沒有空格數組裏面自減後:indexofNew=14
indexofOriginal自減前:11
indexofOriginal自減後:10
indexofOriginal:10
indexofNew:14
tempArray[indexofOriginal]:p
 

沒有空格數組裏面自減前:indexofNew=14
沒有空格:tempArray[indexofOriginal]=p
沒有空格賦值後:tempArray[indexofNew]=
indexofNew:13
tempArray[indexofOriginal]:p
沒有空格數組裏面自減前:indexofNew=13
沒有空格:tempArray[indexofOriginal]=p
沒有空格賦值後:tempArray[indexofNew]=

沒有空格數組裏面自減後:indexofNew=12
indexofOriginal自減前:9
indexofOriginal自減後:8
indexofOriginal:8

indexofNew:12
tempArray[indexofOriginal]:a
沒有空格數組裏面自減前:indexofNew=12
沒有空格:tempArray[indexofOriginal]=a
沒有空格賦值後:tempArray[indexofNew]=y

沒有空格數組裏面自減後:indexofNew=11
indexofOriginal自減前:8
indexofOriginal自減後:7
indexofOriginal:7
indexofNew:11
tempArray[indexofOriginal]:h
沒有空格數組裏面自減前:indexofNew=11
沒有空格:tempArray[indexofOriginal]=h
沒有空格賦值後:tempArray[indexofNew]=p
沒有空格數組裏面自減後:indexofNew=10
indexofOriginal自減前:7
indexofOriginal自減後:6
indexofOriginal:6
indexofNew:10
tempArray[indexofOriginal]:

出現空格,替換
替換第一個字符後:tempArray[indexofNew]=p
替換第一個字符後:indexofNew=9
替換第二個字符後:tempArray[indexofNew]=a
替換第二個字符後:indexofNew=8
替換第三個字符後:tempArray[indexofNew]=h
替換第三個字符後:indexofNew=7
indexofOriginal自減前:6
indexofOriginal自減後:5
indexofOriginal:5
indexofNew:7
tempArray[indexofOriginal]:e
沒有空格數組裏面自減前:indexofNew=7
沒有空格:tempArray[indexofOriginal]=e
沒有空格賦值後:tempArray[indexofNew]=
沒有空格數組裏面自減後:indexofNew=6
indexofOriginal自減前:5
indexofOriginal自減後:4
indexofOriginal:4
indexofNew:6
tempArray[indexofOriginal]:r
沒有空格數組裏面自減前:indexofNew=6
沒有空格:tempArray[indexofOriginal]=r
沒有空格賦值後:tempArray[indexofNew]=e

沒有空格數組裏面自減後:indexofNew=5 indexofOriginal自減前:4 indexofOriginal自減後:3 indexofOriginal:3 indexofNew:5 tempArray[indexofOriginal]:a 沒有空格數組裏面自減前:indexofNew=5 沒有空格:tempArray[indexofOriginal]=a 沒有空格賦值後:tempArray[indexofNew]=r 沒有空格數組裏面自減後:indexofNew=4 indexofOriginal自減前:3 indexofOriginal自減後:2 indexofOriginal:2 indexofNew:4 tempArray[indexofOriginal]: 出現空格,替換 替換第一個字符後:tempArray[indexofNew]=a 替換第一個字符後:indexofNew=3 替換第二個字符後:tempArray[indexofNew]= 替換第二個字符後:indexofNew=2 替換第三個字符後:tempArray[indexofNew]=e 替換第三個字符後:indexofNew=1 indexofOriginal自減前:2 indexofOriginal自減後:1 替換空格後的字符串: 開始打印數組 We%20are%20happy

相關文章
相關標籤/搜索