【LeetCode】Z 字形變換(JS實現)
問題
今天開始在leetcode刷演算法題,遇到這樣一道題,題目看上去就有點好玩,就進去試了一下:
將一個給定字串 s 根據給定的行數 numRows ,以從上往下、從左到右進行Z 字形排列。
比如輸入字串為 "PAYPALISHIRING"行數為 3 時,排列如下:
P A H N
A P L S I I G
Y I R
輸出結果就是"PAHNAPLSIIGYIR“
思路
最開始,對這樣的題目有一絲絲摸不到頭腦,於是希望可以從這個z字形排列出的結果中找到一些規律。
既然要找規律,我假定一個字串:HELLOGEPINGLI
行號 | |||||||
1 | H | E | I | ||||
2 | E | G | P | L | |||
3 | L | O | I | G | |||
4 | L | N |
那結果如上面所示,應該是HEI(第一行對應的字串)+EGPL(第二行對應的字串)+LOIG(第三行對應的字串)+LN(第四行對應的字串)
於是現在我們有了第一個想法,我們弄一個數組,ROWS,有幾行,這個陣列就有幾項。
下面,我們就需要研究下一個問題點了,我們如何去確定每一行對應的字串是什麼,所以,還是要找一找規律。
首先,我們一看就可以輕鬆的發現,4行的情況下,是每6個字元一個迴圈。如下圖所示,迴圈週期是2*numRows-2。
為什麼是2*numRows-2呢,也很容易。看下面的圖可以明白,兩倍的行數,再去掉頭尾兩個。
下面,我們繼續以之前四行的例子繼續看 字元會出現在哪一行的規律。
rows | ||||
0 | position=0 0%6=0 6-0=6 | position=6 | ||
1 | position=1 1%6=1 6-1=5 | position=5 5%6=5 6-5=1 | position=7 | |
2 | position=2 2%6=2 6-2=4 | position=4 4%6=4 6-4=2 | position=8 | |
3 | position=3 3%6=3 6-3=3 | position=9 |
上圖,position代表的是字元在原字串中的位置,6是2*numRows-2的計算結果(2*4-2=6)。我們不難的發現,行數其實是position%(2*numRows-2)和(2*numRows-2)-position%(2*numRows-2)的最小值。
那麼這樣問題就可以很順利的解決了。
程式碼
var convert = function(s, numRows) {
if (numRows === 1) return s;
const rows = new Array(numRows).fill("");
const period = 2 * numRows - 2;
for(let i = 0; i < s.length; i++) {
rows[Math.min(i % period, period - i % period)] += s[i];
}
return rows.join("");
};