题目:
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"
.
提示:
此题我想到的解法有两种:
- 根据行数声明一个动态字符串数组,然后按照规则中字符的排列顺序一次把字符放到对应的数组元素当中,之后再把这些字符串拼接起来;
- 寻找规律,直接按照规律拼出所要求的字符串。
从执行时间上来看,第二种方案更快一些。
代码:
第一种解法:
class Solution { public: string convert(string s, int numRows) { // 如果只需要一行,直接返回 if (numRows == 1) return s; string *res = new string[numRows]; string final; int size = s.size(), i = 0, row = -2; // 按照字符出现的顺序,把字符放到相应的数组元素中 while (i < size) { // 先由上到下 for (row += 2; i < size && row < numRows; ++i, ++row) { res[row] += s[i]; } // 再由下到上 for (row -= 2; i < size && row > -1; ++i, --row) { res[row] += s[i]; } } // 拼接 for (int i = 0; i < numRows; ++i) { final += res[i]; } // 别忘了释放指针 delete[] res; return final; } };
第二种解法:
class Solution { public: string convert(string s, int numRows) { // 如果只有一行,直接返回s if (numRows == 1) return s; string res = ""; // step是针对于第一行和最后一行 int step = (numRows - 1) << 1; // 先把第一行搞定 for (int i = 0; i < s.size(); i += step) { res += s[i]; } // 再搞定中间的几行 int row = 2; while (row < numRows) { // 中间这几行的间隔数会在两个数之间交替变换,因此再for循环中增加一个if判断 for (int j = row - 1; j < s.size(); ) { res += s[j]; j += (numRows - row) << 1; if (j < s.size()) { res += s[j]; j += (row - 1) << 1; } } ++row; } // 把最后一行搞定 for (int i = numRows - 1; i < s.size(); i += step) { res += s[i]; } return res; } };