题目
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
L D R
E O E I I
E C I H N
T S G
解题思路
- 对字符串进行分组
- 根据行数计算出每一组字符串数
- 同样根据行数和字符串数计算出Z字形变换的列数
- 新建一个字符串,迭代遍历Z字形的每一个元素,判断是否存在字符,如果存在计算出该位置原来的字符串的索引,追加到新的字符串。
值得注意的是Swift字符串访问元素效率很低,可以转换成Character数组,效率是原来的3倍。
Swift代码
class Solution {
func convert(_ s: String, _ numRows: Int) -> String {
if s.isEmpty || numRows <= 1 {
return s
}
var array = s.map({$0})
let groupCount = 2 * numRows - 2
let columnPerGroup = numRows - 1
var numColumns = columnPerGroup * (array.count / groupCount)
let remainder = array.count % groupCount
numColumns += (remainder / numRows) + (remainder % numRows)
var string = ""
for y in 0..<numRows {
for x in 0..<numColumns {
var i = 0
let groupIndex = x / columnPerGroup
let groupRemainder = x % columnPerGroup
if groupRemainder == 0 {
i = groupCount * groupIndex + y
if i < array.count {
string.append(array[i])
}
} else {
if groupRemainder + y + 1 == numRows {
i = groupCount * groupIndex + (groupCount - y)
if i < array.count {
string.append(array[i])
}
}
}
}
}
return string
}
}