# 6.ZigZag Conversion <span class='tag' data-diff='medium'></span> {%hackmd RN5D4nggQRO8wzNqxuvlNw %} ## 題目 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) ``` P A H N A P L S I I G Y I R ``` And then read line by line: `"PAHNAPLSIIGYIR"` Write the code that will take a string and make this conversion given a number of rows: ``` string convert(string s, int numRows); ``` **Example 1:** ``` Input: s = "PAYPALISHIRING", numRows = 3 Output: "PAHNAPLSIIGYIR" ``` **Example 2:** ``` Input: s = "PAYPALISHIRING", numRows = 4 Output: "PINALSIGYAHRPI" Explanation: P I N A L S I G Y A H R P I ``` ## 思路 這題其實滿有趣的,有點像在做加密的感覺。對於這種有規律性的題目,最重要的就是先找到他們的規律性,把`numRows`為3、4、5、6的情況寫出來後,就發現它的規律如下: - 第一列的間隔與最後一列的index間隔是 $2(n-1)$ - 中間其他列的間隔則是兩個數交替 - 這兩個數在第 $k$ 列為 $2(n-k)$ 、 $2k$,而第一列也可以視為 $k=0$ 與 $k=n$ 的特殊情況 - 每一列第一個數為 $k\ mod\ n$ 所以先宣告一個生成indices的函數,給予每一列的兩個間隔,還有起始編號與字串長度,就可以回傳一串indices。 ```javascript const getIndices = (a, b, min, max) => { let flag = true, indices = []; do{ if(!indices.includes(min)) indices.push(min); min += flag ? a : b; flag = !flag; }while(min < max); return indices; } ``` 接者loop過每一列,把所有生成的indices接起來,就可以得到答案想要的字串排序順序 ```javascript let k = numRows - 1, zigIndices = []; for(let i = 0; i <= k; i++){ let indices = getIndices((k-i) * 2, i * 2, i, s.length); zigIndices = zigIndices.concat(indices); } ``` 之後,在return時,只要依照這個陣列裡面的index,就可以做出重組的字串了 ```javascript s = s.split(""); return zigIndices.map(i => s[i]).join(""); ``` 此外,一開始可以先判斷一些例外情況,像是`numRows`只有1,或是字串長度小於`numRows`時,可以直接回傳該字串。