题目:
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"
.
思路:
这是一道easy级别的题目,主要问题在于边界情况的考虑。有两种思路:
1、有几行就申请几个字符串,最后用一个字符串把一行的字符收集起来。在依次遍历字符串的时候,可以设置一个递增标记flag,可以为1或者-1,代表下一个是增加还是减少。该思路简单直观,但是需要额外的O(n)空间。
2、可以从第一行到最后一行依次构造。在构造每行字符串的过程中,我们都可以通过公式推导出该行字符串中的具体字符,因此可以直接构造。该思路的好处是空间复杂度为O(1)。
两种思路的时间复杂度都是O(n)。下面的代码实现的是第二种思路。
代码:
class Solution {
public:
string convert(string s, int numRows) {
if (numRows <= 1) return string(s);
int column_num = std::ceil(s.length() / (2 * numRows - 2.0));
string zigzag;
int index = 0, length = s.length();
for (int i = 0; i < column_num; i++) // output the first row
{
index = i * (2 * numRows - 2);
if (index < length) zigzag += s[index];
}
for (int j = 1; j < numRows - 1; j++) // output the middle rows
{
for (int i = 0; i < column_num; i++)
{
index = i * (2 * numRows - 2) + j;
if (index < length) zigzag += s[index];
index = (i + 1) * (2 * numRows - 2) - j;
if (index < length) zigzag += s[index];
}
}
for (int i = 0; i < column_num; i++) // output the last row
{
index = i * (2 * numRows - 2) + numRows - 1;
if (index < length) zigzag += s[index];
}
return zigzag;
}
};