【LeetCode】ZigZag Conversion(Z 字形变换)

时间:2023-03-09 07:58:34
【LeetCode】ZigZag Conversion(Z 字形变换)

这道题是LeetCode里的第6道题。

题目要求:

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

比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:

L   C   I   R
E T O E S I I G
E D H N

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

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

string convert(string s, int numRows);

示例 1:

输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"

示例 2:

输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释: L D R
E O E I I
E C I H N
T S G

题目虽然很长,但是题目本身并不难,却相当的花时间。这道题l类似于我之前做过的螺旋矩阵(回形取数),打打草稿发现规律,找出函数关系就行了。

拿例子2说明:

输入:s = “LEETCODEISHIRING”,numRows = 4

Z字排列如下:

【LeetCode】ZigZag Conversion(Z 字形变换)【LeetCode】ZigZag Conversion(Z 字形变换)

转换成对应的下标索引为:

【LeetCode】ZigZag Conversion(Z 字形变换)

首先可以发现第一行的索引添加量和Z字的行数numRows有关系:IndexAdd=2*numRows-2

例如当 numRows = 3 时:

【LeetCode】ZigZag Conversion(Z 字形变换)

IndexAdd=2*3-2=4

根据这个特性首先可以解决第一行,同理解决最后一行。

解决完首尾行后中间行怎么办呢?因为中间行有斜对角的字符,要如何处理?其实不难,拿例子2来说,第二行1和7中间一个,7和13中间一个,第三行2和8中间一个,8和14中间一个,也就是说中间行每隔 IndexAdd 就会有一个字符,前提是不超出范围。numRows = 3 时,中间第二行也符合这个规律。而且这些字符还符合另一规律:例子2中5在 i=1 行(索引值),1和5差4,4在 i=2行(索引值),2和4差2。也就是说中间字符和左边字符的差值为 IndexAdd-2*i,所以中间行这样处理:第一个是 j=i,然后中间字符 j=j+IndexAdd-2*i,再是 j=j+2*i,这样走完一轮相当于 j=j+IndexAdd,一直循环。

说明:i 是行的索引值,不是第 i 行。第一行的索引值为0,第二行的索引值为1,等等。

提交代码:

class Solution {
public:
string convert(string s, int numRows) {
int i=0,j,len=s.length(),IndexAdd=(numRows-1)*2;
if(numRows==1||numRows>=s.length())return s;
string res;
while(1){
j=i;
if(i==0||i==numRows-1){
while(j<len){res+=s[j];j=j+IndexAdd;}
i++;
if(i==numRows)break;
}else{
while(j<len){res+=s[j];j=j+IndexAdd-2*i;
if(j<len){res+=s[j];j=j+2*i;}}
i++;
}
}
return res;
}
};

提交结果:

【LeetCode】ZigZag Conversion(Z 字形变换)

个人总结:

题目不难只要发现其中规律就能很好的解决。一开始处理的时候弄混淆了下标和字符的关系,浪费了些时间。