题目
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
示例 1:
输入: s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR"
题解
方式一:模拟
思路最简单
public String convert(String s, int numRows) {
// 不需要处理
int len = s.length();
if (len <= numRows || numRows == 1) {
return s;
}
// 模拟,把字符放到数组里面;这里数组长度应该还能小一点,懒得算了
// 想优化可以把二位数组换成StringBuilder数组
char[][] simulation = new char[numRows][len];
int m = 0;
int n = 0;
char[] chars = s.toCharArray();
int count = 0;
int index = 0;
while (count < len) {
// down
while (m < numRows && count < len) {
simulation[m++][n] = chars[index++];
count++;
}
m -= 2;
n++;
// up
while (m >= 0 && count < len) {
simulation[m--][n++] = chars[index++];
count++;
}
m += 2;
n--;
}
// 遍历数组取结果
StringBuilder sb = new StringBuilder();
for (int i = 0; i < simulation.length; i++) {
for (int j = 0; j < simulation[0].length; j++) {
if (simulation[i][j] != 0) {
sb.append(simulation[i][j]);
}
}
}
return sb.toString();
}
方式二:利用flag转向(大神思路)
public String convert(String s, int numRows) {
int n = s.length();
if (n <= numRows || numRows == 1) {
return s;
}
List<StringBuilder> list = new ArrayList<>();
for (int i = 0; i < numRows; i++) {
list.add(new StringBuilder());
}
int flag = -1;
int i = 0;
for (char c: s.toCharArray()) {
list.get(i).append(c);
// 到边界转向
if (i == 0 || i == numRows - 1) {
flag = -flag;
}
i += flag;
}
StringBuilder ans = new StringBuilder();
for (StringBuilder sb: list) {
ans.append(sb);
}
return ans.toString();
}
总结
算法:模拟