ZigZag Conversion
The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
Exmaple:
|
|
And then read line by line: “PAHNAPLSIIGYIR”
Write the code that will take a string and make this conversion given a number of rows:
|
|
convert(“PAYPALISHIRING”, 3) should return “PAHNAPLSIIGYIR”.
提示 | 解題應用 |
---|---|
String | 觀查規律 |
Default:
|
|
解答思路:
numRows = 3
最初的想法是拆成三大塊分上、中、下,第一列PAHN就是利用 nRows+1(4) 為index的倍數放到array開頭,接著到第三列YIR同上 nRows-1(2) 的倍數放到array尾端,中間就只要將上述剩餘的依序放入,因為就算經過convert,如果仔細觀查橫的輸出好比YIR,這三個字元在原本的PAYPALISHIRING字串出現的順序不變,所以不用擔心,至於這三大塊該如何塞入同一array的位置,從上塊來說只要符合倍數就原本 array[index/(numRows+1)] 放入,而下塊也是符合倍數就 array[len(s)-len(s)/(numRows+1)] 中間的只要知道上塊的index到哪從後頭接著放入就對了。
顯然我完全搞錯了ZigZag的重點… 所以最初想法不看也沒差。
這裡給的範例實在太少,很可能會因為沒接觸過導致不清楚什麼是ZigZag而寫的方向錯誤,所以再附上一些結果來讓人了解。
Example:
|
|
|
|
花點時間應該可以看出有特殊規律,不過看討論這類的題目在面試上沒什麼太大意義,所以通常不會出現的樣子。從最初的想到的來看我也許能夠拆成上、中、下塊,只是這次的中塊大了點,不過似乎有更好的做法,拆成直線↓一組與斜線↗一組,以 numRows=4 來說,PIN ASG YH PI為直線↓,LI AR為斜線↗
(直線規律)第一排的PIN為例,P與I的indx變化(經過點)可以發現:
原點 | 直線↓剩餘數 | 斜線↗數 | 直線↓剩餘數 |
---|---|---|---|
P | AYP | AL | I |
index | numRows - (index + 1)%(numRows + (numRows - 2)) | numRows - 2 | (index + 1)%(numRows + (numRows - 2)) |
合併之後下一點的index
index = index + numRows - (index + 1)%(numRows + (numRows - 2)) + numRows - 2 + (index + 1)%(numRows + (numRows - 2)) = index + 2*(numRows - 1)
另外也可以發現到只有 numRows=2 時,沒有任何的斜點,因為斜線數 (numRows-2=0) 。
|
|
至於 numRows=1 根本跟問題給的字串一樣,所以在最一開始就要篩掉。
|
|
(斜線規律)看來沒辦法像直線一樣直接得到絕對位置簡單,只好從直線的相對位置找起(numRows=4為例):
在上一個直線規律中我們從 P→I 找關係,而這次我們則要找直線與斜線的相對關係,所以就找 A→L ,不過後來反而發現 A→S→L ,是有脈絡可尋的,而且 S→L 之間的關係與該兩點所在的行數(第幾橫排)有密切關係。
row為該兩點所在的行數
原點 | 中點 | 斜點 |
---|---|---|
A | S | L |
index | 2*(numRows - 1) | -2(row - 1) |
其中原點到中間我們可以由先前直線規律求得,合併之後斜點的index:
index = index + 2*(numRows - 1) - 2(row - 1)
程式碼解說:
在go中,從字串提出的字元型別都是rune,你可以想成是直接轉成ascii,最大的好處在於最後將這些rune陣列轉成string回傳時,你不需要一個個去join到空字串裡頭,而是將整個rune陣列直接轉成string,非常的方便且快速。
|
|
這邊我用index的0~numRows來取出每一橫排的第一個值,而next就是套前述所提的直線與斜線規律所整理出的結論,因為我是從0開始算橫排,所以就不需 (row-1) ,透過觀察例子我們可以發現斜點不會與第一橫排 (index=0) 和最後一排 (index=numRows) 同一排,在找斜點的相對位置時也有可能是中點不存在而斜點存在,這些都要在最後的判斷式過慮。
|
|
完整程式碼:
|
|
總結:
ZigZag就是將一字串做鋸齒狀排列來讓你找出規律。
(直線規律)絕對位置 index = index + 2(numRows - 1)
(斜線規律)相對位置 index = index + 2(numRows - 1) - 2(row - 1)