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 s, int numRows);
Example 1:
**Input:** s = "PAYPALISHIRING", numRows = 3
**Output:** "PAHNAPLSIIGYIR"
Example 2:
**Input:** s = "PAYPALISHIRING", numRows = 4
**Output:** "PINALSIGYAHRPI"
**Explanation:**
P I N
A L S I G
Y A H R
P I
Example 3:
**Input:** s = "A", numRows = 1
**Output:** "A"
Constraints:
1 <= s.length <= 1000
s
consists of English letters (lower-case and upper-case),','
and'.'
.1 <= numRows <= 1000
这道题刚开始看了半天没看懂是咋样变换的,上网查了些资料,终于搞懂了,就是要把字符串摆成一个之字型的,比如有一个字符串 “0123456789ABCDEF”,转为 zigzag 如下所示:
当 numRows = 2 时:
0 2 4 6 8 A C E
1 3 5 7 9 B D F
当 numRows = 3 时:
0 4 8 C
1 3 5 7 9 B D F
2 6 A E
当 numRows = 4 时:
0 6 C
1 5 7 B D
2 4 8 A E
3 9 F
可以发现,除了第一行和最后一行没有中间形成之字型的数字外,其他都有,而首尾两行中相邻两个元素的 index 之差跟行数是相关的,为 2nRows - 2, 根据这个特点,可以按顺序找到所有的黑色元素在原字符串的位置,将它们按顺序加到新字符串里面。对于红色元素出现的位置(Github 上可能无法正常显示颜色,请参见博客园上的帖子)也是有规律的,每个红色元素的位置为 j + 2numRows-2 - 2*i, 其中,j为同一行前一个黑色数字的在原字符串中的位置 index,i为当前行数。 比如当 n = 4 中的那个红色5,它的位置为 1 + 2 x 4-2 - 2 x 1 = 5,为原字符串的正确位置。知道了所有黑色元素和红色元素位置的正确算法,就可以一次性的把它们按顺序都加到新的字符串里面。代码如下:
解法一:
class Solution {
public:
string convert(string s, int numRows) {
if (numRows <= 1) return s;
string res;
int size = 2 * numRows - 2, n = s.size();
for (int i = 0; i < numRows; ++i) {
for (int j = i; j < n; j += size) {
res += s[j];
int pos = j + size - 2 * i;
if (i != 0 && i != numRows - 1 && pos < n) res += s[pos];
}
}
return res;
}
};
若上面解法中的规律不是很好想的话,我们也可以用下面这种更直接的方法来做,建立一个大小为 numRows 的字符串数组,为的就是把之字形的数组整个存进去,然后再把每一行的字符拼接起来,就是想要的结果了。顺序就是按列进行遍历,首先前 numRows 个字符就是按顺序存在每行的第一个位置,然后就是 ‘之’ 字形的连接位置了,可以发现其实都是在行数区间 [1, numRows-2] 内,只要按顺序去取字符就可以了,最后把每行都拼接起来即为所求,参见代码如下:
解法二:
class Solution {
public:
string convert(string s, int numRows) {
if (numRows <= 1) return s;
string res;
int i = 0, n = s.size();
vector<string> vec(numRows);
while (i < n) {
for (int pos = 0; pos < numRows && i < n; ++pos) {
vec[pos] += s[i++];
}
for (int pos = numRows - 2; pos >= 1 && i < n; --pos) {
vec[pos] += s[i++];
}
}
for (auto &a : vec) res += a;
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/6
类似题目:
Binary Tree Zigzag Level Order Traversal
参考资料:
https://leetcode.com/problems/zigzag-conversion/
https://www.cnblogs.com/springfor/p/3889414.html
https://leetcode.com/problems/zigzag-conversion/discuss/3403/Easy-to-understand-Java-solution
LeetCode All in One 题目讲解汇总(持续更新中…)
(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,快快加入吧~)
微信打赏
|
Venmo 打赏
—|—
转载请注明来源于 Grandyang 的博客 (grandyang.com),欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 grandyang@qq.com