将一个给定字符串 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);
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I
输入:s = "A", numRows = 1
输出:"A"
public class Solution {
public string Convert(string s, int numRows) {
int n = s.Length, r = numRows;
if (r == 1 || r >= n) {
return s;
}
int t = r * 2 - 2;
int c = (n + t - 1) / t * (r - 1);
char[][] mat = new char[r][];
for (int i = 0; i < r; ++i) {
mat[i] = new char[c];
}
for (int i = 0, x = 0, y = 0; i < n; ++i) {
mat[x][y] = s[i];
if (i % t < r - 1) {
++x; // 向下移动
} else {
--x;
++y; // 向右上移动
}
}
StringBuilder ans = new StringBuilder();
foreach (char[] row in mat) {
foreach (char ch in row) {
if (ch != 0) {
ans.Append(ch);
}
}
}
return ans.ToString();
}
}
public class Solution {
public string Convert(string s, int numRows) {
int n = s.Length, r = numRows;
if (r == 1 || r >= n) {
return s;
}
StringBuilder[] mat = new StringBuilder[r];
for (int i = 0; i < r; ++i) {
mat[i] = new StringBuilder();
}
for (int i = 0, x = 0, t = r * 2 - 2; i < n; ++i) {
mat[x].Append(s[i]);
if (i % t < r - 1) {
++x;
} else {
--x;
}
}
StringBuilder ans = new StringBuilder();
foreach (StringBuilder row in mat) {
ans.Append(row);
}
return ans.ToString();
}
}
class Solution:
def convert(self, s: str, numRows: int) -> str:
n, r = len(s), numRows
if r == 1 or r >= n:
return s
t = r * 2 - 2
ans = []
for i in range(r): # 枚举矩阵的行
for j in range(0, n - i, t): # 枚举每个周期的起始下标
ans.append(s[j + i]) # 当前周期的第一个字符
if 0 < i < r - 1 and j + t - i < n:
ans.append(s[j + t - i]) # 当前周期的第二个字符
return ''.join(ans)