描述:
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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
较优的解决方案:
class Solution {
public String convert(String s, int numRows) {
if(numRows < 2) return s;
List<StringBuilder> rows = new ArrayList<StringBuilder>();
for(int i = 0; i < numRows; i++) rows.add(new StringBuilder());
int i = 0, flag = -1;
for(char c : s.toCharArray()) {
rows.get(i).append(c);
if(i == 0 || i == numRows -1) flag = - flag;
i += flag;
}
StringBuilder res = new StringBuilder();
for(StringBuilder row : rows) res.append(row);
return res.toString();
}
}
思路解析:
今天又聪明了一点点....刚开始的思路是你要几行我就声明几个数组,然后根据规律放到数组里,然后从构建好的数组中读取数据进行整合,惊不惊喜,意不意外,就是这么一点脑子都不动....然后发现这个规律好像不大好找,因为是 “Z” 字形排列,在 Z 的最后一划有点麻烦,但是我们真的需要将整个字符串分成几行(几个数组吗),其实不然,我们只需要找到这个排列的规律即可,然后根据规律对字符串进行重组,所以就对字符串中的每个字符进行了编号,以确定他在哪一行,详情请看下面的示例。
2行
LEETCODEIDHIRING
1212121212121212
3行
1232123212321232
4行
1234321234321234
5行
1234543212345432
通过这个示例可以看到,一个Z字其实是一个增减增的过程,我们可以进一步转化,从整体去看的话,将增减增看做转折点,则可以看到在1和最大行数时进行转折,转换为index则为0和 numRows时进行转折,有了这个思路,就可以进行构造,使用numRows个StringBuilder分别存储每一行的字符串,使用flag来标记上升(1)和下降(-1)的转折点(这个用的太妙了,佩服佩服),使用 i来标记每一行,使用flag来对i进行修改,在转折点的时候对flag进行反转,最后将所有的StringBuilder进行合并即可。
我的方法是用了map来对整个String的字符进行了分类,key为行号,value为一个list来存储该行的字符,最后进行合并。