给定一个字符串 s
和一个行数 numRows
,请按照从上往下、再从下往上的“Z”字形排列这个字符串,并按行输出最终结果。例如:
输入:
s = "PAYPALISHIRING"
numRows = 3
Z 字形排列如下:
P A H N
A P L S I I G
Y I R
输出字符串为:“PAHNAPLSIIGYIR”
目标:将字符串按 Z
字形排列后,再逐行读取,拼成新的字符串。
Z字形结构特点:
numRows = 3
,Z 周期宽度为 4
:下(3)+ 斜上(1) = 4
。numRows = 4
,Z 周期宽度为 6
:下(4)+ 斜上(2) = 6
。因此,我们只需按照这个顺序依次将字符“填”到对应的行中,最后逐行拼接输出即可。
func convert(_ s: String, _ numRows: Int) -> String {
// 边界情况:如果只有一行,直接返回原字符串
if numRows == 1 || numRows >= s.count {
return s
}
// 创建 numRows 个空字符串用于收集每一行的字符
var rows = Array(repeating: "", count: numRows)
var currentRow = 0 // 当前字符所在的行
var goingDown = false // 控制方向是否向下
// 遍历字符串中的每个字符
for char in s {
// 将字符添加到当前行
rows[currentRow] += String(char)
// 如果到达最顶部或最底部,则改变方向
if currentRow == 0 || currentRow == numRows - 1 {
goingDown.toggle()
}
// 根据方向决定下一行
currentRow += goingDown ? 1 : -1
}
// 拼接所有行的字符
return rows.joined()
}
n
为字符串 s
的长度。rows
,最多 n
个字符分布在其中。cycleLen = 2 * numRows - 2
i
,通过 i % cycleLen
判断它属于哪一行。func convert(_ s: String, _ numRows: Int) -> String {
if numRows == 1 || numRows >= s.count { return s }
var rows = Array(repeating: "", count: numRows)
let cycleLen = 2 * numRows - 2
for (i, char) in s.enumerated() {
let pos = i % cycleLen
let row = pos < numRows ? pos : cycleLen - pos
rows[row] += String(char)
}
return rows.joined()
}
goingDown
,逻辑更数学化,适合喜欢用索引推理的同学。方法 | 易读性 | 实现难度 | 性能 | 推荐场景 |
---|---|---|---|---|
按行构建 | ✅ 高 | ⭐⭐ | ✅ 优 | 新手友好,适合面试 |
索引模拟周期 | ⭐ 中 | ⭐⭐⭐ | ✅ 优 | 偏数学推理,适合进阶 |
func printZMatrix(_ s: String, _ numRows: Int) {
if numRows == 1 || numRows >= s.count {
print(s)
return
}
let cycleLen = 2 * numRows - 2
let numCols = (s.count / cycleLen + 1) * (numRows - 1)
var matrix = Array(repeating: Array(repeating: " ", count: numCols), count: numRows)
var row = 0, col = 0
var index = 0
let chars = Array(s)
while index < chars.count {
// 向下
for r in 0..<numRows where index < chars.count {
matrix[r][col] = String(chars[index])
index += 1
}
// 向右上
for r in stride(from: numRows - 2, through: 1, by: -1) where index < chars.count {
col += 1
matrix[r][col] = String(chars[index])
index += 1
}
col += 1
}
// 打印矩阵
for row in matrix {
print(row.joined())
}
}
printZMatrix("PAYPALISHIRING", 4)
输出示例:
P I N
A L S I G
Y A H R
P I