题目描述:(力扣)
废话后面说,直接贴代码
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1)return s;
string ans("");
int down = 2 * numRows - 4, up = 2;
//设置up、down的初值
for (int i = 0; i < numRows; i++) {
int k = i,flag = 1;
//第一行和最后一行的循环
if (i == 0 || i == numRows - 1) {
while (k < s.size()) {
ans+=s[k];
k = k + 2*numRows-2;
}
continue;
}
//中间行(第一行和最后一行之间的行)的循环
else
while (k < s.size()) {
ans += s[k];
flag++ % 2 == 1 ? k += down : k += up;
//用flag判断每次循环读取需跳跃的值
}
down -= 2;
up += 2;
//每结束一次中间行的循环up和down要变一次
}
return ans;
}
};
提交,代码效率:
(大神看到这可以慢走了(..) )
看不懂代码思路的同学,可以耐心再听我唠一唠(ノ゚▽゚)
仔细观察一下这个图案,我们能想到最快的办法就是先把“LDR”提出来,再依次把“EOEII”、“ECIHN”、“TSG”提取出来,将它们连起来就好了。难点在于怎么知道‘L’的下一个提取目标是‘D’呢。
(在这里,我把图案中每一个Z字形中间出现的列数标记为m,像上图,当n=4的时候,m=2。不难发现m和n之间的规律是m=n-2。)
**情况1:观察第一行下标变化 ( 当n=4时,L跳跃到D,下标需要增加6=n+m) 可以发现这种情况适用于第一行和最后一行。
**情况2:中间行下标变化(1<?<n)
n=4,下标跳跃序列:
2-> +4,+2,+4,+2
3-> +2,+4,+2,+4
n=5,下标跳跃序列:
2-> +6,+2,+6,+2
3-> +4,+4,+4,+4
4-> +2,+6,+2,+6
n=6,下标跳跃序列:
2-> +8,+2,+8,+2
3-> +6,+4,+6,+4
4-> +4,+6,+4,+6
5-> +2,+8,+2,+8
相信你们已经发现了一些啥了,没错,中间行的跳跃序列排在一块后,从列看下来一列递减(down)一列递增(up),所以我们只需要知道他们的初始值与m、n的关系就可以了。
int down = ( m + n) - 2, up = 2;
//设置up、down的初值
每行的下标跳跃只要遵守当前设定好的up、down值,就可以将中间行的字符串顺利提取。这时候,我们只需要在提取第n行和第n+1行之间,将up、down做递增和递减:
down -= 2;
up += 2;
//每结束一次中间行的循环up和down要变一次
好了,这就是这周分享的全部内容啦
(我太懒了只挑了我觉得自己做的还挺好的这一题)
继续加油吧奥利给!