6. ZigZag Conversion
- 找规律
题目
The string "PAYPALISHIRING"
is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3)
should return "PAHNAPLSIIGYIR"
.
思路
- 找规律。
如下是长为21的字符串的5行Z形转换:
0 8 16
1 7 9 15 17
2 6 10 14 18
3 5 11 13 19
4 12 20
将Z形路线压缩如下:
0 8 16
1 7 9 15 17
2 6 10 14 18
3 5 11 13 19
4 12 20
由上可见,这是一个周期为 N (N = numRows*2 - 2) 的Z形排序,而每一行的序号对应 N 的模是有规律的。
- 复杂性分析:
- 时间复杂度:O(n*m).
- 空间复杂度:O(n).
题解
class Solution {
public:
string convert(string s, int numRows) {
if (s.size() <= 0 || numRows <= 0) return "";
if (numRows == 1) return s;
int temp = numRows*2 - 2;
string ans;
for (int j = 0; j < numRows; j++) {
for (int i = 0; i < s.size(); i++) {
if (i%temp == j || i%temp == temp-j)
ans += s[i];
}
}
return ans;
}
};
反思
- 注意 nunRows=1 的情况。
在 nunRows=1 时会出现 temp = numRows*2 - 2 = 0 的情况,导致i%temp == j || i%temp == temp-j
出现“division by zero”的错误,因此需要单列出来讨论。
优化代码
class Solution {
public:
string convert(string s, int numRows) {
int size = static_cast<int>(s.size());
// 当行数小于等于1 或 大于原串的size时不用转换
if (numRows <= 1 || numRows >= size) {
return s;
}
// 字符串数组, 装的是行的对应的字符串
vector <string> rowString(numRows);
int rowNum = 1;
// 向下读还是向上读的标志
int flag = 1;
for (int i = 0; i < size; ++i) {
rowString[rowNum-1] += s[i];
if (rowNum == numRows){
flag = -1;
}
if (rowNum == 1) {
flag = 1;
}
rowNum += flag;
}
string result;
for (int i = 0; i < numRows; ++i) {
result += rowString[i];
}
return result;
}
};