题目
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
说明:
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zigzag-conversion/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思考过程
- 首先确定最后是要输出一个新的字符串,新的字符串长度不变,只是元素的位置有变化
问题转化
问题转化为 **如何计算出新字符串中每一位是什么字符?**或者说是如何计算出旧字符串中每一位,应该在新字符串中的哪个位置?
继续思考找规律
- 假如需要分2行
按照原字符串的下标排序为:
0 2 4 6
1 3 5 7
- 假如需要分3行
按照原字符串的下标排序为:
0 4 8
1 3 5 7 9
2 6 10
- 假如需要分4行
按照原字符串的下标排序为:
0 6 12
1 5 7 11 13
2 4 8 10 14
3 9 15
名词
current_column_index
: 当前正在考察的列的第一行的下标next_column_index
: 当前正在考察的列的下一个满列第一行的下标middle_column
:正在考察的列和下一个整列中间的列
图解名词
0 6 12
1 5 7 11 13
2 4 8 10 14
3 9 15
==================
0123456789
其中:
如果数字`0`对应的是正在考察的列,即当前列
那么数字`8`对应的就是下一列
数字`3,5`对应的就是中间列
观察可以发现规律:
假如分 n (从0开始计数,如果实际有4行,n = 3)行:
当前列新字符串下标的计算方式:
current_column_index + n (如果n = 3,并且当前列是第一列(即current_column_index=0)的话,会有四个值:0,1,2,3)
此时有:
next_column_index = 2 * n - 2 + current_column_index
=>
next_column_index = 2 * (n - 1) + current_column_index
中间列新字符串下标的计算方式:
第m行的下标是:(m != 0 && m != n) 即:不是第一行,不是最后一行,只有中间行才有中间列
index_m = next_column_index - m
依次计算每一列,直到`next_column_index`超过字符串的长度
实现
import java.util.HashMap;
import java.util.Map;
public class Solution {
public String convert(String s, int numRows) {
char[] chars = s.toCharArray();
int maxLength = chars.length;
// 如果只分一行或者为空串,直接返回
if (numRows == 1 || s.equals("") || maxLength <= numRows) {
return s;
} else {
// 声明一个和原s一样长的数组,用来存放新数据
char[] zArray = new char[maxLength];
// zArray当前填充下标
int arrayIndex = 0;
// 一次计算每一行的字符
for (int row = 0; row < numRows; row++) {
// 每一列的开始下标
int i = 0;
// 下标不超过字符串的长度
while (i + row < maxLength) {
// 计算出下一列的下标
int maxIndex = 2 * numRows - 2 + i;
// 处理本列的字符
zArray[arrayIndex++] = chars[i + row];
// 处理本列和上一列之间的字符,第一行和最后一行是不需要处理的
if ((row != 0 && row != numRows - 1) && maxIndex - row < maxLength) {
zArray[arrayIndex++] = chars[maxIndex - row];
}
// 将下一列的下标传递给i,下一个循环开始处理下一列的字符
i = maxIndex;
}
}
// 需要处理的最大index
return new String(zArray);
}
}
}