之字形打印字符串,看到题有点蒙。先写一下找规律
对于convert("PAYPALISHIRING", 3),有
P(0) |
|
A(4) |
|
H(8) |
|
N(12) |
A(1) |
P(3) |
L(5) |
S(7) |
I(9) |
I(11) |
G(13) |
Y(2) |
|
I(6) |
|
R(10) |
|
|
括号内为对应字符的下标
如果是convert("PAYPALISHIRING", 4)呢?
P(0) |
|
|
I(6) |
|
|
N(12) |
A(1) |
|
L(5) |
S(7) |
|
I(11) |
G(13) |
Y(2) |
A(4) |
|
H(8) |
R(10) |
|
|
P(3) |
|
|
I(9) |
|
|
|
就这样找规律,可以看到对于string convert(string text, int nRows)可以以前nRows – 1列为一个周期。解释清楚一点:
对于convert("PAYPALISHIRING",3)前2(2= nRows – 1 = 3 – 1)列,包含字符的个数为4,因此循环周期为4
对于convert("PAYPALISHIRING",4) 前3(3= nRows – 1= 4 – 1)列,包含字符的个数为6,因此循环周期为6
周期用T表示,找到了周期与nRows之间的关系,就可以进一步找规律。
从上面两个表总结规律:
for (int i = 0; i < nRows; i++) //从第0行到第nRows – 1行
if(i == 0){
//对于第0行,第一个出现的字符是s中下标为0的字符,接下来出现的字符的下标依次加上周期就可以
}
else if(i < nRows - 1){
//对于中间的行寻找字符下标出现的规律
//以第二行为例,第二行第一个出现的字符是s中下标为1的字符,接下来出现的字符的下标为T-1,第三个出现的字符的小标为T+1
//用i表示就是,第一个出现的字符下标为i,接下来出现的字符下标为T-i。那么T-i与i之间的距离为T-i-i = T – 2 * i。第三个出现的字符的下标为T+i,T+i与T-i之间的距离为(T+i)-(T-i)= 2 * i。
//找到了下标出现的规律就可以解题啦
}
else {
//对于最后一行的规律与第0行一样,起始小标为nRows-1,不断加上周期就可以啦
}
class Solution {
public:
string convert(string s, int numRows) {
if(numRows <= 1 || s.empty())
return s;
int modNum = numRows * 2 - 2;//每次循环的个数
int len = (int)s.size();//字符串s的长度
string result;//保存最后的结果
for(int i = 0; i < numRows; i++) {
vector<int> vec;
if(i == 0 || i == numRows- 1){
vec.push_back(modNum);
vec.push_back(modNum);
}
else {
vec.push_back(modNum - i - i);
vec.push_back(2 * i);
}
for(int j = i, k = 1; j < len; ) {
result += s[j];
k = (k + 1) & 0x1;
j = j + vec[k];
}
}
return result;
}
};