题目
字符串"PAYPALISHIRING" 是使用z字形的模式排列的。给定行数为numRows,按Z字型排列如下:
P A H N
A P L S I I G
Y I R
然后按行输出: "PAHNAPLSIIGYIR"
请编写代码实现上述功能,返回转换后的字符串:
string convert(string s, int numRows);
示例1:
输入: s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR"
示例2:
输入: s = "PAYPALISHIRING", numRows = 4
输出: "PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I
示例3:
输入: s = "A", numRows = 1
输出: "A"
解法1:找规律
- n=3,中间空n-2列。一次转折需要的数量是 n + n-2。
- 只需要一次遍历,找出所在行即可:
- k = i % (n + n - 2) 第几组
- if(k > n) r = k - (k - n) // 倒着
- else r = i
function convert(s: string, numRows: number): string {
if (s.length <= numRows) return s; // 只有一组
if (numRows < 2) return s; // 只有一行
const ret = new Array(numRows).fill(1).map((d) => []);
const gourpSize = numRows + numRows - 2;
for (let i = 0; i < s.length; i++) {
const k = i % gourpSize; // 组内第几个
let row = k;
if (k + 1 > numRows) {
const over = k + 1 - numRows; // 折回几行
row = numRows - over - 1;
}
ret[row].push(s[i]);
}
// 确定返回值
return ret.reduce((str, curr) => str + curr.join(''), '');
}
优化
function convert(s: string, numRows: number): string {
// 思路:找规律
// n=3,中间空n-2列。一次转折需要的数量是 n + n-2。
// 只需要一次遍历,找出所在行即可:
// k = i % (n + n - 2) 第几组
// if(k > n) r = k - (k - n) // 倒着
// else r = i
if (s.length <= numRows) return s; // 只有一组
if (numRows < 2) return s; // 只有一行
const ret = new Array(numRows).fill('');
const gourpSize = numRows + numRows - 2;
for (let i = 0; i < s.length; i++) {
const k = i % gourpSize; // 组内第几个
let row = k;
if (k + 1 > numRows) {
const over = k + 1 - numRows; // 折回几行
row = numRows - over - 1;
}
ret[row] += s[i];
}
// 确定返回值
return ret.join('');
}