LeetCode6.Z字形变换
题目描述
/**
* 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
* 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
*
* P A H N
* A P L S I I G
* Y I R
* 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
* 请你实现这个将字符串进行指定行数变换的函数:
*/
思路分析
//思路分析:
//1. 先确定这个字符串展开后的最少行数,原则上是numRows,
// 但是如果s.length < numRows,那么展开是最少行数应该为 s.length
//2. 确定好展开的行数后,考虑这些字符在每行如何存储,可以考虑使用字符串长度可变的StringBuffer来存储每一行
// 然后将每一行的StringBuffer存放在一个List集合中
//3. 考虑这些字符如何Z字形存储的问题,因为最后要打印按行存储的字符串,所以在存储字符的时候不用考虑存储后的形状,
// 只需要将字符存入指定的行即可
//4. 定义两个指针 curRow指向当前行,direct 表示添加字符的方向,
// 假定direct = true表示向下添加字符,direct = false,表示向上添加字符,
// 当direct指向第一行或者最后一行时,改变方向
//5. 字符添加完毕后,遍历集合中的StringBuffer即可
//6. 详解见源码
源码及分析
/**
* @param s 给定的字符串S
* @param numRows 给定的字符串按照多少行进行Z字形展开
* @return
*/
public String convert(String s, int numRows) {
//先进行数据校验
if (numRows == 1) {
return s;
}
//拿到Z自行变换的行数
int min = Math.min(s.length(), numRows);
//总共有min行,第一行索引为0,最后一行索引为 min - 1
//创建存储StringBuffer的集合
ArrayList<StringBuffer> list = new ArrayList<>();
//向每行添加一个StringBuffer容器
for (int i = 0; i < min; i++) {
list.add(new StringBuffer());
}
//定义两个指针curRow和direct
//默认刚开始在第一行,往下走
int curRow = 0;
boolean direct = true;
//遍历字符串的字符,向指定位置添加字符
for (char c : s.toCharArray()) {
//如果向下添加
if (direct) {
//向当前可变字符串中添加字符
list.get(curRow).append(c);
//每添加依次,当前行+1
curRow++;
//判断是否到达最后一行
if (curRow == min) {
//如果到达最后一行,改变direct的方向,重置当前行curRow
direct = false;
curRow -= 2;
}
} else {
//向下添加
list.get(curRow).append(c);
//每添加一个字符,当前行-1
curRow--;
//判断是否到达第一行
if (curRow == -1) {
//如果到达第一行,改变方向,重置当前行
direct = true;
curRow += 2;
}
}
}
//循环结束后所有的字符已经按z自行变换添加完毕
//拿到字符串返回即可
StringBuffer stringBuffer = new StringBuffer();
for (StringBuffer buffer : list) {
//字符串拼接
stringBuffer = stringBuffer.append(buffer);
}
//测试
//stringBuffer = list.get(1);
return new String(stringBuffer);
}