# Z 字形变换
# 题目
将一个给定字符串 s
根据给定的行数 numRows
,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING"
行数为 3 时,排列如下:
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
提示:
1 <= s.length <= 1000
s
由英文字母(小写和大写)、','
和'.'
组成1 <= numRows <= 1000
力扣🔗:https://leetcode-cn.com/problems/zigzag-conversion (opens new window)
# 解题思路
- 首先定义
T = numRows * 2 - 2
为 Z 字符变换后的一个周期,类似一个 V 字形。 - 然后创建一个长度为
numRows
的数组,其中每个元素值(默认为空字符串)代表 Z 字符变换后的每一行字符组成的字符串,索引作为行数。 - 依次遍历字符串的每一个字符,通过
T
和索引i
计算出当前字符应该保存在哪一行,然后存入上述数组当中。 - 最后依次组合上述数组中的每个元素值,即 Z 字符变换后的结果组成的字符串。
# 代码实现
/**
* @param {string} s
* @param {number} numRows
* @return {string}
*/
function convert(s, numRows) {
const l = s.length
if (l <= numRows || numRows === 1) return s
const tempArr = new Array(numRows).fill('') // 每个元素代表 Z 字变换后的每一行,保存的是每行字符组成的字符串
const T = 2 * numRows - 2 // 一个 V 字形周期
for (let i = 0; i < l; i++) {
const m = i % T
const row = Math.min(m, T - m) // 计算出要保存到哪一行
tempArr[row] += s[i] // 添加该字符到对应索引(行)
}
return tempArr.join('')
}