不知道用什么顶部图了,直接套用每日一题的好了。
今天加练的原因是前一道题实在不咋地,思来想去再做一题罢,LeetCode 6. Z 字形变换
来看题目。

题目

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:

1
2
3
P   A   H   N
A P L S I I G
Y I R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:”PAHNAPLSIIGYIR”。

请你实现这个将字符串进行指定行数变换的函数:

1
string convert(string s, int numRows);

##示例
示例 1:

1
2
3
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例 2:

1
2
3
4
5
6
7
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I

示例 3:

1
2
输入:s = "A", numRows = 1
输出:"A"

题解

模拟!是模拟!我突然发现我已经做了两三天模拟了x。其实关于这道题我们只需要找到其中的规律即可,我们来看看这个所谓的 “z字形排列”。

1
2
3
4
5
@   @   @       0     8           16
@ @@ @@ 1 7 9 15 17
@ @ @ @ @ 2 6 10 14 18
@@ @@ @ 3 5 11 13 19
@ @ @ 4 12 20

就是这样的排列,然后我们需要按行来输出,用下标来表示:

1
0 8 16 1 7 9 15 17 2 6 10 14 18 3 5 11 13 19 4 12 20

看出什么情况了吗?
让我们再简化一下这该死的阵列。

1
2
3
4
5
@ @ @     0   8     16
@@@@@ 1 7 9 15 17
@@@@@ 2 6 10 14 18
@@@@@ 3 5 11 13 19
@ @ @ 4 12 20

和前面是一样的,这次呢?
看出来了吧。
第一行的情况:
8 - 0 = 8 16 - 8 = 8
和它们同列的情况:
9 - 1 = 8 10 - 2 = 8
11 - 3 = 8 20 - 12 = 8
他们都在长列。

那短列的情况呢?
15 - 7 = 8 14 - 6 = 8
它们也相差 8 。

我们得出结论,它们隔一列的下标都差 8 。

换个 numRows = 3 看看?

1
2
3
@ @ @       0   4   8
@@@@@ 1 3 5 7 9
@ @ @ 2 6 10

情况好像不太一样了,这次隔列相差 4 ,怎么会这样?这个隔列相差 x 个单位肯定与 numberRows 有关系。

稍微计算一下可以发现 x = 2 ( numberRows - 1 ),您看看是不是这样?

直接清晰明了了有没有!

虽然我们的第0,2,4,……列能够计算了,但是1,3,5,……怎么办呢?我们只要知道第 1 列的元素下标就能算出剩下的了。

再观察一下可以发现是 ``x = 2(numberRows-n-1)’’ (这里的 n 是第 n 行),我们发现变量以后计算公式就方便多了。

可以开始写代码了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
string convert(string s, int numRows) {
if(numRows==1 || numRows>s.size()) //当出现这两种情况时只需要输出原 s
return s;
int n=0;
string ans="";
int k=0,k1=0;
while(ans.size()<s.size())
{
ans+=s[k];
k+=2*(numRows-1); //指向长列的下一个下标
if(n<numRows-1 && n>0 &&k1<s.size())//当 n<1 且 n>numRows 时有短列参与
{
ans+=s[k1];
k1+=2*(numRows-1); //指向短列的下一个下标
}
if(k>=s.size()) //当每行的下标都超出了s.size() 我们就知道该轮到下一行了
{
n++,k=n,k1=n+2*(numRows-n-1);
continue;
}
}
return ans;
}
};

PS

简单吧!我想了一下午!(

我发现这个题目有非常多的公式可以计算出下标结果,所以会有很多种解法,我这个只是其中一种解法,有不同见解欢迎下方讨论!

刷题惯例:

此解法非唯一解,且不一定是最好的解法,如果您有更好的解法,欢迎在评论区中提出。