1. 程式人生 > >替換空格

替換空格

面試 特殊字符 .com 字符串長度 快的 必須 %20 i++ copy

題目:請實現一個函數,將一個字符串中的空格替換成“%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).

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

考慮時間復雜度為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),比第一個思路要快。

技術分享

public class ReplaceSpaces {
    //計算字符串中包含的空格個數  
    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){  
        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();  
        //字符數組增加長度後  
        int newLength = testString.length()+ getBlankNum(testString)*2;  
        char[] tempArray = new char[newLength];  
        System.arraycopy(testString.toCharArray(), 0, tempArray, 0, testString.toCharArray().length);  
        int indexofOriginal = length - 1;  
        int indexofNew = newLength -1;  
        System.out.println("未替換空格時的字符串:");  
        printArray(testString.toCharArray());  
        while(indexofOriginal >=0 && indexofOriginal != indexofNew){  
            if(tempArray[indexofOriginal]==‘ ‘){  
                tempArray[indexofNew--]=‘0‘;  
                tempArray[indexofNew--]=‘2‘;  
                tempArray[indexofNew--]=‘%‘;  
            }else{  
                tempArray[indexofNew--]= tempArray[indexofOriginal];  
            }  
            indexofOriginal--;  
        }  
        System.out.println("替換空格後的字符串:");  
        printArray(tempArray);  
    }  
    public static void main(String[] args){  
        String str = "We are happy";  
        replaceAllBlank(str);  
    }  
}  

替換空格