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"
.
题解:
没有任何技巧,就是找规律。我们将列中元素数等于行数的列称为主列。
由例子可以看出,除了第一行和最后一行,每一行的主列之间都会有一个值,关键就是在于找出这个值的某种规律。
主列之间的位置差值(L 和 A)为 2*numRows - 2。中间值与同处此行中间值之前的元素(P 和 A)的位置差值为 2*numRows - 2 - 2 * 此元素所在的行(以0为起始)
0 6 C
1 5 7 B D
2 4 8 A E
3 9 F
对于主列之间的位置差值。只需找到第一行主列之间的位置差值即可,因为主列从第一行到最后一行元素的位置坐标同步增长。对于行数为 n 的情况,某一主列的元素数显然等于行数 n,此主列到下一个主列之间共有 n - 2 个中间元素(减去的2是因为第一行和最后一行没有中间元素),故主列之间的位置差值为 2n - 2
对于中间元素的位置确定
x-(2n-2) x i = 0 差值 无
` x-1 x+1 i = 1 2
` x-2 x+2 i = 2 4
` x-3 x+3 i = 3 6
` ······································
x-(n) x-(n-2) x+(n-2) i = n-2 2(n-2)
x-(n-1) x+(n-1) i = n-1 无
可见对于某一行 i,主列与中间元素的差值随着行数的增加而翻倍,具体为 差值 = 2 * i
1 class Solution { 2 public: 3 string convert(string s, int numRows) { 4 if (numRows < 2) 5 return s; 6 string res; 7 int n = s.size(); 8 int len = 2 * numRows - 2; 9 for (int i = 0; i < numRows; ++i) { 10 for (int j = i; j < n; j += len) { 11 res += s[j]; 12 int mid = j + len - 2 * i; 13 if (i != 0 && i != numRows - 1 && mid >= 0 && mid < n) 14 res += s[mid]; 15 } 16 } 17 18 return res; 19 } 20 };