06 N字形变换
不要混日子,小心日子把你混了
对于题目的理解
比如说,我给一个字符串,LEETCODE,行数为3,然后按照N字形排列,就是下面这个排列方式。排列完之后正常读取,结果就是LCETOEED。这叫做N字形变换。
这个例子里给的行数就是3,往下排三行,然后往右往上走。
chatGPT
思路
- 边界情况/特殊情况:就给一行,或者给的行数和字符串的长度是一样的,那么就直接返回原来的字符串
- 创建一个长度为numRows的字符数组rows,用于存储每行的字符
。。。没抄完,但是我已经理解了。
我的理解:
- 准备一个数组,类型是StringBuilder,StringBuilder[] rows = new StringBuilder[numRows];容量为给定的行数 numRows,每一个数组元素代表一行。为什么每个数组元素代表一行呢?这里困扰了很久,其实很简单,玄机就在于声明的是StringBuilder类型的。我们在排列的时候是从上往下排列的,所以这里也是从上往下填充数组,每个元素代表一行。当这一列填充结束的时候,就去下一列,仍旧是对row[index]这个元素,也就是对应行的元素,但是这里是append,自然就把这一行元素拼接上来了
- 定义一个index ,初始值为0,用来标志是哪一行;
- 定义一个step,初始值是1,用来标记是向上走还是向下走,1表示向下,-1表示向上
- 考虑边界情况:
- index==0;此时在第一行,应该往下走。step设置为1,index = index+step,这样的话就会是一直在向下走
- 向下走到index = numRows-1,表示走到最下面一行了,该向上走了,这个时候把step设置为-1,index= index+step,这样就相当于在向上走。
- 遍历字符串s
- 遍历结束以后,再去遍历数组,拼接,就是N字形变换之后的结果了。
上代码:
/**
* 首先要理解怎么算是N字变换
* 一个正常的字符串,按照给定的行数,从上到下,斜着向上,再向下,就像N字一样
*
* 解决这个问题的思路是假如给了4行,那就申请一个StringBuilder数组,大小容量也是4
* 遍历给定的字符S,从上往下,向数组元素添加,但是这里的添加是append,下次走到这一行,仍旧append,这样就拼进去了
* 虽然我知道这样讲可能没讲明白,那我在换个说法
*
* 1. 每个数组元素代表一行的字符串,注意这里的一行指的是N字形排列之后的一行
* 2. 题目给了多少行,数组里就有多少个元素,用了StringBuilder这个类型,就可以直接拼接,拼接一整行。
* 3. N字形边界情况:一开始是向下,然后到了最底下,应该向上走了。所以我们需要两个变量,一个用来指示从上往下到第几行,一个用来指示
* 要不要转换方向。这里不用考虑向右走,因为向右走就是在数组元素后面append一个字符。当index是0的时候,应该向下走,可以让index+1,
* 当index是给定的行数numRows-1的时候,应该向上走,就是index-1。
* @param s
* @param numRows
* @return
*/
class Solution {
public String convert(String s, int numRows) {
// 如果行数是1或者是字符串的长度,直接返回字符串
if (numRows == 1 || s.length() <= numRows) {
return s;
}
// 准备数组用来存放字符
StringBuilder[] rows = new StringBuilder[numRows];
// 初始化数组
for (int i = 0; i < numRows; i++) {
rows[i] = new StringBuilder();
}
// 标记在哪一行
int index = 0;
// 标记往下走还是往上走
int step = 1;
// 遍历字符串
for (char c : s.toCharArray()) {
rows[index].append(c);
if (index == 0){
// 此时表示最上面一行,应该是往下走,就+1;直到走到else里,说明到底了
step = 1;
} else if (index == numRows - 1) {
// 这里说明到底了,就-1,往上走,直到index == 0;
step = -1;
}
index += step;
}
// 拼接字符串
StringBuilder result = new StringBuilder();
for (StringBuilder row : rows) {
result.append(row);
}
return result.toString();
}
}
划重点:
我一开始想,可能是用二维数组来记录,因为有横竖的类似于表格的排列,所以很长一段时间内无法理解为什么是一个一维数组就能解决 StringBuilder[] rows = new StringBuilder[numRows];
巧妙的地方在于 StringBuilder
,数组容量是行数,列数不用考虑,因为StringBuilder可以append,往后无限增加列,这就相当于是二维数组了。但是这里有一点不得不注意,你要对数组初始化。