题目
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”
示例 2:
输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:
解题:
解法一:找规律。
一开始我的想法是,最左边一列可以存储numRow个字符,中间对角线(不包含顶角两点)可以存储numRow-2个字符,然后依次循环。利用矩阵来存储z字变换后的字符,然后输出矩阵。但是,矩阵matrix[i][j]坐标很难计算。
解法二:直达结果。
题目要求我们输出的结果是从左到右逐行输出,参考大神解法,直接忽略z字形这个形式,也就是说,既然输出的结果是连续的字符串,那么把z的形式压缩一下,就可以使解法简单很多。
可以看到,通过压缩,我们只要在遍历字符串的时候,将字符串添加至对应的row[i]就可以了。
需要注意的点:
1.row循环的顺序是:row[1]→row[2]→row[3]→row[2]→row[1]→row[2]→row[3]→row[2]→row[1]…
也就是先从上到下,到达最下一行,从下到上返回。我们可以通过设置一个flag值,来标志现在遍历的方向。限定条件是,当遍历到第一行或最后一行时,改变flag的正负来改变遍历方向。
2.StringBuilder的命名空间是using System.Text;
StringBuilder和string比较,当修改StringBuilder时,它不用开辟一个新的StringBuilder,而是直接扩充原有空间;string则是开辟一个新的string存储字符串。
StringBuilder添加字符串,使用的是StringBuilder.Append(char);添加在字符串末尾。
public string Convert(string s, int numRows) {
if (numRows < 2) return s;
List<StringBuilder> rows = new List<StringBuilder>();
for(int j = 0; j < numRows; j++) { rows.Add(new StringBuilder()); }
int i = 0, flag = -1;
foreach (Char c in s)
{
rows[i].Append(c);
if (i == 0 || i == numRows - 1) flag = -flag;
i += flag;
}
StringBuilder res = new StringBuilder();
foreach (StringBuilder row in rows)
{
res.Append(row);
}
return res.ToString();
}
代码参考:https://leetcode-cn.com/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/
大神的图解思路很清晰,推荐去看。