内容纲要
题目
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
请你实现这个将字符串进行指定行数变换的函数:string convert(string s, int numRows);
提示
1 <= s.length <= 1000
s
由英文字母(小写和大写)、','
和'.'
组成1 <= numRows <= 1000
思路
认真思考过这道题的同学肯定知道传入的字符串中每一个字符都隐性的对应一个数字下标,最大是 numRows,最小是 0,从 0 按顺序先从小到大递增到 numRows-1 后又从大到小递减到 0,如此反复到字符串结尾。
例如: 传入字符串为 "PAHNAPLSIIGYIR", numRows 为 4, numRows-1 = 3 则其对应的数字下标为:
P A H N A P L S I I G Y I R
0 1 2 3 2 1 0 1 2 3 2 1 0 1
我们可以通过数字下标的判断来拼接字符串。全程思路在代码演示中给出。
/**
* @author: LoungeXi
**/
public class Solution {
public String convert(String s, int numRows) {
// 定义存放数字下标的 List 集合
List<Integer> indexList = new ArrayList<>();
// 定义结果集
StringBuilder result = new StringBuilder();
// 为每一行要存入的字符都创建一个 StringBuilder , StringBuilder 放在 List 集合中
List<StringBuilder> rowsList = new ArrayList<>();
for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
rowsList.add(new StringBuilder());
}
// 得到传入字符串的长度,减少方法调用
int length = s.length();
// 定义哨兵查看目前添加的数字下标是否达到字符串结尾
int now = 0;
// 未达到字符串结尾继续循环
while (now < length) {
// 添加本轮数字下标的左半段
for (int flag = 0; flag < numRows; flag++) {
if (now < length) {
indexList.add(flag);
now++;
} else {
break;
}
}
// 添加本轮数字下标的右半段
for (int flag = numRows - 2; flag > 0; flag--) {
if (now < length) {
indexList.add(flag);
now++;
} else {
break;
}
}
}
// 根据数字下标在对应的 StringBuilder 中加入字符
for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
for (int flag = 0; flag < indexList.size(); flag++) {
// 若得到数字下标与 StringBuilder 的索引相同则加入字符
if (indexList.get(flag) == rowIndex) {
rowsList.get(rowIndex).append(s.charAt(flag));
}
}
}
// 拼接返回
for (StringBuilder row : rowsList) {
result.append(row);
}
return result.toString();
}
}
优化
因为以上代码过于冗杂,因此对代码进行了优化,提高了性能,增强了可读性,但是思路没有变化。全程思路在代码演示中给出。
/**
* @author: LoungeXi
**/
public class Solution {
public String convert(String s, int numRows) {
// 若传入字符串的长度只有 2 可以直接返回
if (numRows < 2) {
return s;
}
// 为每一行要存入的字符都创建一个 StringBuilder , StringBuilder 放在 List 集合中
List<StringBuilder> rows = new ArrayList<>();
for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
rows.add(new StringBuilder());
}
// 定义好每一行的 StringBuilder 的索引 rowIndex
int rowIndex = 0;
// 这里 flag 的定义是为了传入字符串能找到各自应该加入的 StringBuilder
int flag = -1;
//循环加入字符
for (char c : s.toCharArray()) {
// 根据对应的数字下标将字符添加到对应的 StringBuilder
rows.get(rowIndex).append(c);
// 若 rowIndex == 0 代表数字下标需要递增 flag = 1,若 rowIndex == numRows - 1 代表数字下标需要递减 flag = -1
if (rowIndex == 0 || rowIndex == numRows - 1) {
flag = -flag;
}
// 递增或递减语句
rowIndex += flag;
}
//拼接返回
StringBuilder result = new StringBuilder();
for (StringBuilder row : rows) {
result.append(row);
}
return result.toString();
}
}