Leetcode Algorithm 006. ZigZag Conversion
ZigZag Conversion
给定一个字符串,按照规定的zigzag走法排列之后,按行取出字符形成一个新的字符串
解题思路
首先要明白zigzag走法是什么意思。
题目给了我们一个例子:"PAYPALISHIRING"
用了3行的zigzag走法会是:
P A H N
A P L S I I G
Y I R
看起来还是不太懂?现在画一个4行的zigzag走法:
P I N
A L S I G
Y A H R
P I
5行的zigzag走法:
P H
A S I
Y I R
P L I G
A N
这样是不是清楚多了?Zigzag走法其实就是先走满一列,再沿着斜线方向往回走,走到第一行再次往下走。
其实我们可以找到其中原本字符串在zigzag走法中规律:
0 8
1 7 9
2 6 10 ...
3 5 11 13
4 12
0 2n-2
1 2n-3 2n-1
... ... ... ...
n-2 n 3n-4 3n-2
n-1 3n-3
假设原本的字符串是s
,经过n
行的zigzag走法之后,某行的行号是i
,那么行首的元素将会是s[i]
。第i
行的下一个元素通过两个间隔来决定,一个是step1 = 2*n - 2 - 2*i
,另外一个是step2 = 2*i
。知道这条数学规律之后,我们可以很容易地处理它了。
要注意的是当step1
或者step2
为0的时候恰好是第0
行和第n-1
行,要做特殊处理。
另外,当n==1或者n>=s.size()
的时候无需进行zigzag处理,直接返回原来的字符串即可。
代码
#include<iostream>
using namespace std;
class Solution {
public:
string convert(string s, int numRows) {
int length = s.size();
if (numRows == 1 || numRows >= length)
return s;
string result = "";
for (int i = 0; i < numRows; i++) {
int index = i;
int step1 = 2 * numRows - 2 - 2 * i;
int step2 = 2 * i;
if (index >= length)
break;
result += s[index];
while (true) {
if (step1 != 0) {
index += step1;
if (index < length)
result += s[index];
else
break;
}
if (step2 != 0) {
index += step2;
if (index < length)
result += s[index];
else
break;
}
}
}
return result;
}
};
测试样例
int main() {
Solution s;
cout << s.convert("AB", 3) << endl;
cout << s.convert("PAYPALISHIRING", 5) << endl;
cout << s.convert("PAYPALISHIRING", 4) << endl;
cout << s.convert("PAYPALISHIRING", 3) << endl;
cout << s.convert("PAYPALISHIRING", 2) << endl;
cout << s.convert("PAYPALISHIRING", 1) << endl;
return 0;
}
输出
AB
PHASIYIRPLIGAN
PINALSIGYAHRPI
PAHNAPLSIIGYIR
PYAIHRNAPLSIIG
PAYPALISHIRING