将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “
L
E
E
T
C
O
D
E
I
S
H
I
R
I
N
G
LEETCODEISHIRING
LEETCODEISHIRING” 行数为
3
3
3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:" L C I R E T O E S I I G E D H N LCIRETOESIIGEDHN LCIRETOESIIGEDHN"。
请你实现这个将字符串进行指定行数变换的函数:
s
t
r
i
n
g
string
string
c
o
n
v
e
r
t
(
s
t
r
i
n
g
convert(string
convert(string
s
s
s,
i
n
t
int
int
n
u
m
R
o
w
s
)
;
numRows);
numRows);
示例
1
1
1:
输入:
s
s
s = “
L
E
E
T
C
O
D
E
I
S
H
I
R
I
N
G
LEETCODEISHIRING
LEETCODEISHIRING”,
n
u
m
R
o
w
s
=
3
numRows = 3
numRows=3
输出: “
L
C
I
R
E
T
O
E
S
I
I
G
E
D
H
N
LCIRETOESIIGEDHN
LCIRETOESIIGEDHN”
示例
2
2
2:
输入:
s
s
s = "
L
E
E
T
C
O
D
E
I
S
H
I
R
I
N
G
"
,
n
u
m
R
o
w
s
=
4
LEETCODEISHIRING", numRows = 4
LEETCODEISHIRING",numRows=4
输出: “
L
D
R
E
O
E
I
I
E
C
I
H
N
T
S
G
LDREOEIIECIHNTSG
LDREOEIIECIHNTSG”
解释:
L D R
E O E I I
E C I H N
T S G
思路:
1)找规律。从行出发,我们可以很简单的发现半个 Z Z Z字元素个数为 2 ∗ n u m R o w s − 2 2 * numRows - 2 2∗numRows−2,以此为基准,得到下列规律
- 第 0 0 0行,元素下标为 i ( 0 ) i(0) i(0), i + 2 ∗ n u m R o w s − 2 i + 2 * numRows - 2 i+2∗numRows−2, i + 2 ∗ ( 2 ∗ n u m R o w s − 2 ) i + 2 * (2 * numRows - 2) i+2∗(2∗numRows−2), i + 3 ∗ ( 2 ∗ n u m R o w s − 2 ) i + 3 * (2 * numRows - 2) i+3∗(2∗numRows−2)
- 第 n u m R o w s − 1 numRows - 1 numRows−1行,元素下标为 i ( n u m R o w s − 1 ) i(numRows - 1) i(numRows−1), i + 2 ∗ n u m R o w s − 2 i + 2 * numRows - 2 i+2∗numRows−2, i + 2 ∗ ( 2 ∗ n u m R o w s − 2 ) i + 2 * (2 * numRows - 2) i+2∗(2∗numRows−2), i + 3 ∗ ( 2 ∗ n u m R o w s − 2 ) i + 3 *(2 * numRows - 2) i+3∗(2∗numRows−2)
- 其余行元素下标, i i i, 2 ∗ n u m R o w s − 2 − i 2 * numRows - 2 - i 2∗numRows−2−i, 2 ∗ n u m R o w s − 2 + i 2 * numRows - 2 + i 2∗numRows−2+i, 2 ∗ ( 2 ∗ n u m R o w s − 2 ) − i 2 *(2 * numRows - 2) - i 2∗(2∗numRows−2)−i
- 可以看出,当为第 0 0 0行或 n u m R o w s − 1 numRows - 1 numRows−1行时,该行的元素下标变化幅度都为 2 ∗ n u m R o w s − 2 2 * numRows - 2 2∗numRows−2
- 当不为这两行时,同时计算两个元素,差为 2 ∗ n u m R o w s − 2 − 2 ∗ i 2 * numRows - 2 - 2 * i 2∗numRows−2−2∗i
class Solution {
public:
string convert(string s, int numRows) {
if (s.size() <= 1 || numRows <= 1)
return s;
string str;
int n = s.size(), cyclelen = 2 * numRows - 2;
for (int i = 0; i < numRows; ++i) {
for (int j = 0; j + i < n; j += cyclelen) {
str += s[j + i];
//如果为其他行,则需计算半个Z字中的相邻元素,差值为cyclelen - 2 * i
if (i != 0 && i != numRows - 1 && j + cyclelen - i < n) {
str += s[j + cyclelen - i];
}
}
}
return str;
}
};
2)以行计算。将每一行的元素存入一个数组中,通过 b o o l bool bool变量 n e x t next next判断存上一行还是下一行;当 n e x t next next为 t r u e true true时,则 r o w + 1 row + 1 row+1,反之 r o w − 1 row - 1 row−1,当为第 0 0 0行或第 n u m R o w s − 1 numRows - 1 numRows−1行时,需要反向,则令 n e x t = ! n e x t next = !next next=!next;遍历完之后,将元素按行存入 s t r i n g string string中返回
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1)
return s;
vector<string> rows(max(numRows, (int)s.size()));
int row = 0;
bool next = false;
for (char c : s) {
rows[row] += c;
if (row == 0 || row == numRows - 1)
next = !next;
row += next ? 1 : -1;
}
string str;
for (string row : rows)
str += row;
return str;
}
};