题目
给定⼀个字符串,然后按写竖着的 「z」的⽅式排列字符,就是下边的样⼦。
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。https://leetcode.cn/problems/zigzag-conversion
| | | ↓↗ ↓↗
| | | |
| | | |
| |
有几行数据和 numRows 一致
String s = “PAYPALISHIRING”; numberrows = 4
outpus str = “PINALSIGYAHRPI”;
一、思路
解法二的分析图片
二、题解
public class Test06 {
public static void main(String[] args) {
System.out.println(convert01("PAYPALISHIRING", 4)); //PINALSIGYAHRPI
System.out.println(convert02("PAYPALISHIRING", 4)); //PINALSIGYAHRPI
}
/**
* 对原有字符串 按规则做转换
* 引入了遍历⽅向标志, 按顺序遍历并拼接到每行字符串上
* @param s
* @param numRows
* @return
*/
public static String convert01(String s, int numRows) {
//numRows 为1 或 字符串长度小于等于numRows ,返回原有字符串
if(numRows == 1 || s.length()<= numRows) {
return s;
}
// 竖Z型排列, 需要几行字符串拼接在一起, 和numRows 有关
List<StringBuilder> rows = new ArrayList<>();
for (int i = 0; i < Math.min(numRows, s.length()); i++) {
rows.add(new StringBuilder());
}
//指示字符放在当前第几行
int curRow = 0;
//当前字符 保存当前的遍历⽅向
boolean goingDown = false; //可以做标志,是加一行,还是减一行
for (char c : s.toCharArray()) {
rows.get(curRow).append(c);
if (curRow == 0 || curRow == numRows -1) {
goingDown = !goingDown; //遍历到两端,需要改变⽅向
}
curRow += goingDown ? 1: -1;
}
//拼接所有行的字符
StringBuilder ret = new StringBuilder();
for (StringBuilder row : rows) {
ret.append(row);
}
return ret.toString();
}
/**
* 对原有字符串 按规则做转换
* 分析每行字符在原字符串的索引规律 进行拼接
* @param s
* @param numRows
* @return
*/
public static String convert02(String s, int numRows) {
//numRows 为1 或 字符串长度小于等于numRows ,返回原有字符串
if(numRows == 1 || s.length()<= numRows) {
return s;
}
StringBuilder ret = new StringBuilder();
int cycleLen = 2*(numRows -1); //一个周期的长度
int n = s.length();//字符串长度
for (int i = 0; i < numRows; i++) {
//每行有几个要加步长的字符, 不超出字符长度即可
for (int j = 0; j + i < n; j+= cycleLen) {
ret.append(s.charAt(j + i));
// 去除0行 和最后一行, 其它行有其它字符
if(i!=0 && i!= numRows-1 && j+cycleLen-i <n) {
ret.append(s.charAt(j+cycleLen-i));
}
}
}
return ret.toString();
}
}