题目:
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
。
解题思路:
由于要将字符串s重新排列为多行字符串,所以选用List<StringBuilder>进行字符串存取。
1. 首先确定List集合的大小,当字符串s的长度小于numRows时,List的大小==s.length(),当s的长度大于等于numRows时,List的长度==numRows,所以得出List.size == Math.min(s.length(), numRows);
2. 我们用一个布尔变量direction记录当前字符串的遍历方向,true表示向下构造,false表示向斜上方构造,初始设置为false。并且我们用一个整型变量记录当前遍历行数。
3. 下来我们模拟Z字形字符串的构造过程:每次遍历首先将当前遍历字符append到当前行字符串后边。其次更新当前方向,如果当前行为0,direction由false反转为true,如果当前行为numRows - 1,direction由true反转为false。最后通过direction更新当前行,direction为true,行数加1,direction为false,行数减1。
4. 遍历结束后,将所有字符串按照从上到下的顺序组合起来即为答案。
注意:
如果numRows为1,应直接返回字符串s。否则,在遍历到第二行时,会出现空指针异常。
代码示例:
public class Convert {
public String convert(String s, int numRows) {
if (numRows == 1) return s;
List<StringBuilder> lists = new ArrayList<>();
for (int i = 0; i < Math.min(s.length(), numRows); i++) {
lists.add(new StringBuilder());
}
boolean direction = false;
int curRow = 0;
for (char c : s.toCharArray()) {
lists.get(curRow).append(c);
if (curRow == 0 || curRow == numRows - 1) direction = !direction;
curRow += direction ? 1 : -1;
}
StringBuilder str = new StringBuilder();
for (StringBuilder sb : lists)
str.append(sb);
return str.toString();
}
}