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 RAnd 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"
.
第一次看到这个题目的人,可能不知道ZigZag是什么意思,简单解释一下,就是把字符串原顺序012345……按下图所示排列:
关键是要会如何计算各个字符的位置,这就需要数学知识了,根据特殊推导出公式来。
主要是3个公式:
1 之字形行数为numRows,那么每次重复样出现前的间隔字符为每列的周期是
2*numrows-2;
2 第一行和最尾一行都是存放一个字符的,所以存储的字符为
周期间隔的的字符
3 ,中间行是需要
存储多一个字符的,存储的字符位置是: zigSpan + j - 2*i (其中i为行数,j为该行第几个字符了)
当第一行时,那个字节的位置为1+周期-2;
当是第二行时,
那个字节的位置为2+周期-2*2;
。
。
当是n行的时候,
那个字节的位置 n+周期-2*n;
n小于numrows的;
这样 每个一个周期处理一次 就可以输出之子形;
代码:
class Solution {
public:
string convert(string s, int numRows) {
int len=s.length();
if(len==0 || numRows<2) return s;
string result="";
int circle=2*numRows-2;
for(int i=0;i<numRows;i++)
{
for(int j=i;j<len;j+=circle)
{
result+=s[j];
if(i>0 && i<numRows-1)
{
int temp=j+circle-2*i;
if(temp<len)
{
result+=s[temp];
}
}
}
}
return result;
}
};
别人的:
class Solution {
public:
string convert(string s, int nRows)
{
if(nRows <= 1 || s.length() < 3 || s.length() <= nRows) return s;
string s2;
int zigSpan = nRows*2 - 2;
for (int i = 0; i < nRows; i++)
{
for (int j = i; j < s.length(); j+=zigSpan)
{
s2.push_back(s[j]);
//注意:推导出zigSpan+j-2i的数学公式,一点都不能错
if (i != 0 && i != nRows-1 && zigSpan+j-2*i<s.length())
{
s2.push_back(s[zigSpan+j-2*i]);
}
}
}
return s2;
}
};
class Solution {
public:
string convert(string s, int nRows)
{
if(nRows <= 1 || s.length() < 3 || s.length() <= nRows) return s;
string s2;
int zigSpan = nRows*2 - 2;
for (int i = 0; i < nRows; i++)
{
for (int j = i; j < s.length(); j+=zigSpan)
{
s2.push_back(s[j]);
//注意:推导出zigSpan+j-2i的数学公式,一点都不能错
if (i != 0 && i != nRows-1 && zigSpan+j-2*i<s.length())
{
s2.push_back(s[zigSpan+j-2*i]);
}
}
}
return s2;
}
};
class Solution {
public:
string convert(string s, int nRows) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
string result;
if (nRows < 2) return s;
for (int i = 0;i < nRows;++i) {
for (int j = i;j < s.length();j += 2 * (nRows - 1)) {
result.push_back(s[j]);
if (i > 0 && i < nRows - 1) {
if (j + 2 * (nRows - i - 1) < s.length())
result.push_back(s[j + 2 * (nRows - i - 1)]);
}
}
}
return result;
}
};