来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zigzag-conversion
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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
由规律可得:第行第一个和第二个差2(numRows-line) 或者 2(line - 1)。以示例2为例。
第一行:L和D。2 *(4-1)= 6。L是第1位,D是第7位。差6个。
第二行:E和O。2 (4-2)= 4。E是第2位,O是第6位。差4个。(从T-O)
O和E。2 (2-1)= 2。O是第6位。E是第8位。差2个。(从O-E)
...
第numRows行:和第一行一样。是个例外。
方法
func convert(_ s: String, _ numRows: Int) -> String {
if numRows == 1 {
return s
}
var result:String = ""
for line in 1...numRows {
var currentIndex = line
var isFromBottom = true
while currentIndex <= s.count {
result.append(s[s.index(s.startIndex, offsetBy: currentIndex-1)])
if line == numRows || line == 1{
currentIndex += 2 * (numRows - 1)
}else {
if isFromBottom {
currentIndex += 2 * (numRows - line)
}else {
currentIndex += 2 * (line - 1)
}
isFromBottom = !isFromBottom
}
}
}
return result
}
方法2-速度更快。
func convert(_ s: String, _ numRows: Int) -> String {
guard numRows > 1 else { return s }
var curRow = 0
var arr = Array(s)
var result = ""
for row in 0..<numRows {
var i = 0
var index = i * (2 * numRows - 2) + row
while index < arr.count {
result.append(arr[index])
i += 1
let prevIndex = index
index = i * (2 * numRows - 2) + row
let nextIndex = i * (2 * numRows - 2) - row
if nextIndex < arr.count, nextIndex != index, nextIndex != prevIndex {
result.append(arr[nextIndex])
}
}
}
return result
}