https://leetcode.cn/problems/zigzag-conversion/description/?envType=study-plan-v2&envId=top-interview-150
我们肯定想到用数组来存放一下最后遍历数组组合,因为str<=1000,所以数组长度为1000即可,然后就是遍历字符串,根据Z字形的规律,来决定字符应该放在哪个位置,z字形规律:从上到下(1,0),从左下到右上(-1,+1)依次循环。
public String convert(String s, int numRows) {
if (numRows == 1) return s;
int index = 0;
boolean orientation = true;//true表示从上到下,false表示从左下到右上
int row = 0, col = 0;//代表这个字母要存放的位置
char[][] arr = new char[numRows][s.length()];
while(index < s.length()) {
arr[row][col] = s.charAt(index);
index++;
if(orientation) {//从上到下
row++;
if(row == numRows) {
orientation = false;//改变方向
row -= 2;//因为row++了,所以需要减2
col ++;
}
continue;
}
if(!orientation) {//从左下到右上
row--;
col++;
if (row == -1) {
orientation = true;//改变方向
row += 2;//因为row--了,所以需要加2
}
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] != 0) {
sb.append(arr[i][j]);
}
}
}
return sb.toString();
}
但是因为我们要用一个二维数组存中间结果,所以空间复杂度,时间复杂度比较高,为了优化我们可以找到Z字形变换的规律:
除了用数组记录一下我们还可以找规律,比如: 第一行是两个数相隔2 * numRows - 2, 第二行是相隔numRows - 1 + numRows - 3再隔1这样交替, 第三行是相隔numRows - 2 + numRows - 4再隔2这样交替, …… 总结一下就是numRows - cnt + numRows - 2 - cnt,cnt从0开始,每次加1 当numRows - 2 - cnt == 0的时候代表又是以2 * numRows - 2为周期了,这样我们只要遍历第一列就行 时间复杂度O(n)
public String convert2(String s, int numRows) {
if (numRows == 1) return s;
StringBuilder sb = new StringBuilder();
int cnt = 0;
int currIndex = 0;
for(int i = 0; i < numRows; i++) {
currIndex = i;
while(currIndex < s.length()) {
sb.append(s.charAt(currIndex));
if(i != 0 && i != numRows - 1) {//不是第一行和最后一行
currIndex += numRows - i + numRows - 2 - i;
if(currIndex < s.length()) {
sb.append(s.charAt(currIndex));
}
currIndex += i * 2; //i + 1 + i + 1 - 2
} else if(i != numRows - 1) {//不是最后一行
currIndex += numRows - i + numRows - 2 - i;
} else {
currIndex += 2 * numRows - 2;
}
}
}
return sb.toString();
}