【链接】https://leetcode-cn.com/problems/zigzag-conversion/
题目
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"
思路
思路一:
这类题的思路是找规律,如行数为4时:
第一行:0 - 6 - 12 - 18 ... //步长6 6 6
第二行:1 - 5 - 7 - 11 - 13 ... //步长4 2 4 2
第三行:2 - 4 - 8 - 10 - 14 ... //步长2 4 2 4
第四行:3 - 9 - 15 - 21 ... //步长6 6 6
规律显而易见,当然读者可以自己多试试其他的例子来验证。其实根据"Z"字的特点我们也能直接分析出这样的规律。接下来就是将规律函数化。
- 步长:上述例子中 无论是6 还是4,2交替还是2,4交替,都是和6相关的。那么6又是怎么和层数关联呢?根据图形"Z"来分析,每加1层就会增加2步长,那么步长即为
总层数*2-2
,后文称之为绝对步长。 - 根据步长我们能很快计算第一层的所有下标。那第二层 第n层呢。第二层其实就是
步长-2
,2
交替,第三层是步长步长-4
,4
交替。 - 提炼公式:
步长- 2*(层数-1)
,2*(层数-1)
交替。 - 最后一层和第一层步长一直都是绝对步长。
思路二:
设 numRows 行字符串分别为 s1 , s2,..., sn,则容易发现:按顺序遍历字符串 s 时,每个字符 c 在 ZZ 字形中对应的 行索引先从s1增大至sn,再从sn减小至s1。
…… 如此反复。
因此,解决方案为:模拟这个行索引的变化,在遍历 s 中把每个字符填到正确的行 res[i]
算法流程: 按顺序遍历字符串 s;
- res[i] += c: 把每个字符 c 填入对应行si;
- i += flag: 更新当前字符 c 对应的行索引;
- flag = - flag: 在达到 ZZ 字形转折点时,执行反向。
代码
版本一:本地运行正常,leetcode提示堆益处:
string convert(string s, int numRows) {
int len = s.size();
char *c = new char[len];
memset(c,0,len);
//绝对步长,第一行和最后一行
int size = numRows * 2 - 2;
//记算s下标
int index;
//记录c下标
int count = 0;
//相对步长
int add;
if (numRows < 2) {
return s;
}
for (int i = 0; i < numRows; i++) { //一层一层遍历
index = i;
add = i * 2;
while (index < s.size()) { //超出字符串长度计算下一层
c[count] = s[index];
add = size - add;
if(add == 0){
index +=size;
}else{
index +=add;
}
count++;
}
}
return string(c);
}
版本二:
leetcode运行正常
string convert(string s, int numRows) {
if(numRows < 2) return s;
vector<string> vec(numRows, "");
int i = 0, flag = -1;
for(auto c : s){
//vec[i].append(1,c);
vec[i] += c;
if(i == 0 || i == numRows-1) flag = -flag;
i += flag;
}
string res("");
for(const auto &c : vec) res += c;
return res;
}