這兩天在看《編程珠璣》,第一章就收獲非常的多,真的挺后悔現在才看着本書,第二章有個將字符串逆序的例子,就是比如“this is a string”變成“string a is this”,那么今天就總結一下這個逆序字符串的小專題。
首先假設有人問你:如何將“this is a string”完全逆序,也就是gnirts a si siht
方案一:申請一個同樣大小的空間,直接逆序將字符串保存一遍。
這是我們最容易想到的一種方法,我們只需要找到字符串尾指針就好了,下面就是一段簡單的代碼:
這個代碼的關鍵是找准字符串尾的位置,(每一個字符串以‘\0’結尾)
那么,現在我們的問題增加了,再開一個n,空間太大了,我們必須減少空間。。。
方案二:其實仔細觀察就會發現,逆序其實就是不斷的首尾交換,比如abcde首先是a和e進行交換,接着是b和d交換,這樣以此類推n/2次交換就可以完成任務了,這個的遠離其實就是我們早就會的軸對稱。
寫這個方法的時候,我曾經犯的錯誤就是把right-- 寫成了right++,結果悲劇的段錯誤就出現了,希望大家不要有這樣低級的失誤。
現在問題又的苛刻了,干脆不允許我們用臨時變量了,該如何使字符串逆序,這個時候
方案三:有沒有想起以前有一個經典的問題就是,如何不經過臨時變量如何交換兩個整數,那就是經典的;
a = a + b;
b = a - b; //此時 b = a
a = a - b ; //此時 a = b
其實我們還可以使用一個漸漸被我們遺忘的操作符,那就是異或^,補一點小知識,兩個數異或,比如1101和1001,相同位為0,不同位為1,則結果為0100,所以任何數和0異或的結果都是其本身,一個數和自身異或的結果就是0.
於是上面的代碼其實也可以這樣來寫
a = a ^ b;
b = a ^ b;
a = a ^ b; 哈哈,是不是感覺非常的棒。
有了這個思路的話,接下來實現無臨時變量的交換就變得非常的簡單了
還是那句話,注意符號。。。
最后回歸話題了,我們不是要完全的逆序,而是要求每一個單詞的逆序,比如 “string a is this”,說真的第一次看這個問題就是一下子頭很亂,無從下手,《編程珠璣》中的提示就是逆序的逆序,一下子就有了靈感,我們把這個字符串抽象成ABCD,我們用A~表示其逆序,這樣(A~B~C~D~)~就是DBAC了。通俗的描述就是先對每一個單詞求逆序,得到 siht si a gnirts,然后對整個字符串逆序,也就得到了string a is this
好了,大功告成了,這樣我們一步步的歸納了一下字符串逆序的種種~希望對大家有所幫助。
本文源代碼:https://github.com/octobershiner/Algorithm/tree/master/Reverse