将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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
分析:
本题可以使用数学方法分析,可以直接推导出第i个字符的行和列数。但是推导需要时间并且短时间内公式不一定正确。所以我们采用模拟-输出的放法:模拟将字符按z字形排列,但是不存贮中间结果(每个字符的行列数)直接将字符放到对应行数的队列中,后期只需将所有行拼接在一起输出即可。
class Solution {
public String convert(String s, int numRows) {
List<StringBuilder> list = new ArrayList<>();
for (int i = 0; i < numRows; i++) { //每一行的字符存在一起
list.add(new StringBuilder());
}
int rowNum =0;
boolean up=false; //向上遍历
for (int i = 0; i < s.length(); i++) {
if (up) list.get(rowNum--).append(s.charAt(i));
else if (!up) list.get(rowNum++).append(s.charAt(i));
rowNum = rowNum > numRows-1 ?numRows-1 : rowNum; //控制边界
rowNum = rowNum < 0 ? 0: rowNum;
if (rowNum==0 || rowNum==numRows-1){ //更新遍历方向
up = rowNum==0 ?false:true;
}
}
StringBuilder result = new StringBuilder(); //拼接结果
for (StringBuilder sb:list) {
result.append(sb);
}
return result.toString();
}
}