6、Z字形变换
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
方法一:按行排序
1.1 思路分析
说实话,没做出来,菜鸡一枚,看得题解,官方题解写得也不咋地,就翻了翻其他大佬的,不愧是大佬,清晰明了,通俗易懂。我再简单捋一下,然后直接上截图。
题中的意思是按照N字将字符串排开。定义一个二维数组然后保存成稀疏矩阵也是可以的,不过我们知道行数,但不知道列数。
既然没办法形成稀疏矩阵,我们只需要知道哪些字母属于哪一行也可以。从左到右遍历字符串,将每个字符向不同行分配,最后将每行的字符串起来。
1.2 代码实现
func convert(s string, numRows int) string {
n := len(s)
if numRows == 1{
return s
}
rows := make([][]byte, min(numRows, n)) // 如果长度小于行数,那只需要申请n个切片即可
for i:=0; i<len(rows); i++{
rows[i] = make([]byte, 0)
}
r, flag := 0, -1
for i:=0; i<n; i++{
rows[r] = append(rows[r], s[i])
if r == 0 || r == numRows-1{
flag = -flag
}
r += flag
}
res := make([]byte, 0)
for i:=0; i<len(rows);i++{
res = append(res, rows[i]...)
}
return string(res)
}
func min(a, b int) int{
if a < b{
return a
}
return b
}
1.3 测试结果
1.4 复杂度
- 时间复杂度:O(N)
- 空间复杂度:O(N)
方法二:按行访问
2.1 思路分析
2.2 代码实现
func convert(s string, numRows int) string {
n := len(s)
if numRows == 1{
return s
}
res := make([]byte, 0)
step := 2*numRows-2 // 首尾两行间距
add := 0 // 实际间距
index := 0 // 记录s的下标
for i:=0; i<numRows; i++{
index = i // 记录s的下标
add = 2*i // 实际间距
for index < n{ // 如果到行尾,进入下一行
res = append(res, s[index])
add = step - add // 第一次间距是step -2*i,第二次是2*i,
if i==0 || i==numRows-1{
index += step
}else{
index += add
}
}
}
return string(res)
}
2.3 测试结果
2.4 复杂度
- 时间复杂度:O(N)
- 空间复杂度:O(N)