Problem: 6. ZigZag Conversion
Question:
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”.
解题思路:
/*n=numRows
1 2n-1 4n-3
2 2n-2 2n 4n-4 4n-2
3 2n-3 2n+1 4n-5 .
. . . . .
. n+2 . 3n .
n-1 n+1 3n-3 3n-1 5n-5
n 3n-2 5n-4
*/
ZigZag是将字母按照'Z'字形排列过去的一种模式。实际上是盘山公路的“之”字形,ZigZag在英文中就有蜿蜒、盘山公路的意思
了解完ZigZag是什么就可以开始解题了。
目标:解析给定的字符串使得每一行的每个字母依次组合,第一行组完就第二行…最后就形成给定的字符串。
A G M
B F H L O
C E I K P
D J Q
从上面的字符串可以找出一点规律,看第一行,A的下一个字母是G,两者间隔的距离是 6 (BCDEF),最后一行也是如此,两个连续字母之间的距离都是相等的,有如下规律。
dis = 2*numRows-2
看中间的字母,B和H的间隔也是6,但B的下一个字母是F,第三行C的下一个字母是E,但是观察可以发现,中间行的第一个字母和第二个字母,第三个字母和第四个字母的间隔相同。(在上面的图中,同一行,不相邻的两个字母”间隔”相同)
设中间行的行数为 i(从1开始计数),有如下规律:
dis = 2*numRows-2-i
所以思路如下:
- 第一行和最后一行,result += str[i(当前字母的位置) + dis]
- 中间行数,设第一个字母的行数为 i, 则第二字母的位置为 2*numRows-2-i,往后的字母,根据 dis 依次后移可以得到
代码
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 0 || numRows == 1)
return s;
string result = "";
int n = 0, k = 0;
int cycle = 2*numRows - 2;
for (int i = 0; i < numRows; i++) {
for (int j = i; j < s.length(); j = j + cycle) {
result = result + s[j];
int second = j - i + cycle - i;
if (i != 0 && i != numRows - 1 && second < s.length())
result = result + s[second];
}
}
return result;
}
};