劍指offer 面試題4 替換空格(注意時間效率)

2021-07-04 01:23:07 字數 1766 閱讀 4590

題目:請實現乙個函式,把字串中的每個空格替換成「%20」。

對於這個問題,初見,可能感覺會比較簡單,但隱藏了很多陷阱,需要考慮全面。

陷阱1:由乙個字元,替換為,三個字元,那麼字串肯定變長,需要考慮原字串記憶體是否足夠

陷阱2:空指標檢查,不能忘記

陷阱3:時間複雜度很關鍵

最直觀的做法(從前向後替換):從頭到尾掃面字串,每一次碰到空格字元的時候做替換。由於是把1個字元替換成3個字元,我們必須要把空格後面的所有字元都後移兩個位元組,否則就有兩個字元被覆蓋。

這樣做的話,對於乙個存在多個空格的字串,很明顯存在移動多次的字元。增加了時間複雜度。

這種做法**如下:

/** 一般解法,時間複雜度o(n^2) */

void replace_blank2(char str,int length)

old_len = i; // 原字串的長度

new_len = old_len + j*2; // 新字串的長度

if(new_len >= length) // 檢查記憶體是否足夠

return;

p1 = 0; // p1指向最開始

p2 = old_len; // p2指向結尾

while(str[p1] != '\0')

old_len = old_len + 2;

p2 = old_len; // p2再次指向最後

str[p1++] = '%'; // 空格替換

str[p1++] = '2';

str[p1++] = '0';}}

}

逆向思維做法:從後向前替換,先遍歷整個字串,得出空格總數,從而計算出替換後字串的總長度。這樣就知道了最後面的字元需要移動的總位數,就相當於將後面本來要移動多次的字元,一次性先移掉。然後從後向前替換空格。

這樣所有字元都只需移動一次,時間複雜度大大降低。

如下圖所示:

**如下:

/** 時間複雜度o(n) */

void replace_blank(char str,int length)

len_of_str = i;

num_of_blank = j;

new_len_of_str = len_of_str + num_of_blank*2;

if(new_len_of_str >= length)

return;

p2 = new_len_of_str;

p1 = len_of_str;

while(p1 >= 0 && p2 > p1)

else

//p1--;}}

主函式如下:(可以新增其他測試用例)

int main()

結果如下:

/*點滴積累,我的一小步o(∩_∩)o~*/

替換空格(劍指offer面試題4)

分析 從頭到尾掃瞄字串,遇到空格就替換,導致後面的字元都要向後移,意味著總時間複雜度為o n 2 更好的辦法,從字串後面遍歷替換。先遍歷所有的空格,每多乙個空格,字串長度加2個,也就是說最後替換後的字串長度為原長度 2 空格數,設定兩個指標,指向原始字串末尾和新字串末尾,依次向前遍歷,原始字串指標遇...

劍指offer 面試題4 替換空格

題目由來 在網路程式設計中,如果url引數中含有特殊字元,如空格 等,可能導致伺服器端無法獲得正常的引數值。我們需要將這些特殊符號轉換成伺服器可以識別的字元。轉換的規則是在 後面跟上ascii碼的兩位十六進製制的表示。比如空格的ascii碼是32,即十六進製制的0x20,因此空格被替代成 20 思路...

劍指offer 面試題4 替換空格

由於我在實現的時候使用的是c 的string,所以從後往前複製和從前往後複製,時間複雜度是一樣的。如果使用char 陣列實現,則從後往前複製更高效。重點是掌握這種反向思維。class solution 初始化新string string res s.size 2 countblank,a 必須將si...