0
点赞
收藏
分享

微信扫一扫

力扣第6题-Swift题解: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 <= s.length <= 1000​
  • ​s​​​ 由英文字母(小写和大写)、​​','​​​ 和 ​​'.'​​ 组成
  • ​1 <= numRows <= 1000​

思路

这道模拟题的关键思路是​坐标变换​,即需要对两个字符串的坐标进行映射。

假定输入字符串为​​s​​​,输出字符串为​​p​​​,那么映射的思路分两种,一种是从第一个下标开始遍历​​s​​​,寻找在​​p​​​对应的下标;第二种思路是反过来从第一个下标遍历​​p​​​,寻找在字符串​​s​​中对应的下标。第二种思路会更好计算一点。

观察字符串​​s​​的“前进”规律可以发现,字符串中的字符要么是向下运动,要么是斜线向上运动。

而对于字符串​​p​​,它是负责逐字符行打印​​Z​​型中的每一行的。

计算规律如下:


  1. 对于​​z​​​型的任意第​​i​​​行的起始字符,都对应字符串​​s​​​的第​​i​​个字符。
  2. 对于​​z​​​型的任意字符来说,只要该在​​z​​字型中往右移动一次,要么是通过先向下移动再斜向上移动的方式,要么是通过先斜向上移动再向下移动的方式进行。
  3. 对于首行​​z​​型字符而言,始终往右移一位是通过向下移动再斜向上移动方式进行。
  4. 对于末行​​z​​型字符而言,始终往右移一位是通过向下移动再斜向上移动方式进行。
  5. 对于既非首行也非末行的其它​​z​​型字符而言,从首列开始,往右移动的移动规律是先向下移动再斜向上移动,下一步骤是先斜向上再向下移动交替进行。

利用如上描述的规律,就可以写代码模拟​​z​​​型运动逻辑。通过逐行扫描​​z​​​型字符,即可把对应的字符写入到​​p​​中。

​swift​​代码:

class Solution {
func convert(_ s: String, _ numRows: Int) -> String {
guard numRows > 1 else { return s }
let cs = s.cString(using: .ascii)!
let count = cs.count
var ans: [CChar] = Array(repeating: 0, count: count)

var i1 = 0
var i0 = 0
var row = 0
// 标记下一步移动是先向下,还是先斜向上
var down = true
while i1 < count - 1 {
ans[i1] = cs[i0]
i1 += 1
// 对于不同的移动方式,计算对应的偏移索引
i0 += down ? (numRows-row-1)*2 : row*2
if i0 >= count - 1 {
row += 1
i0 = row
down = row == numRows - 1 ? false : true
} else if row != 0 && row != numRows - 1 {
down.toggle()
}
}

return String(cString: ans)
}
}



举报

相关推荐

0 条评论