题目地址
愚蠢的模拟
最初思路,模拟过程,开数组,竖直向下走,到底了掉头斜向上,到顶了竖直向下,直至遍历数组。
愚蠢的代码
public String convert(String s, int numRows) {
if(numRows<=1) {return s;}
char[][] c = new char[numRows][s.length()];
int r = 0, l = 0;
int direction = 0; // 0 means down and 1 means up
for(int i = 0; i< s.length(); i++) {
c[r][l] = s.charAt(i);
if(direction == 0 && numRows-1>r) {
r++;
if(r==numRows-1) {
direction = 1;
}
}else if(direction == 1 && r>0){
r--;
l++;
if(r==0) {
direction = 0;
}
}
}
String ans = new String();
for(int i = 0; i < c.length; i++) {
for(int j = 0; j < c[0].length; j++) {
if(c[i][j] != '\0') {
ans += Character.toString(c[i][j]);
}
}
}
return ans;
}
稍微高级点的模拟: 按行模拟(fast than 73%)
我们发现,上面的思路里面空间浪费太大,其实,我们观察目标,虽然是z型模拟,但结果是按行排列的字符串,也就是说,我们完全可以将z模拟认为是蛇形模拟
Talking is no use, show you my codes
public String convert(String s, int numRows) {
if(numRows <= 1) return s;
String[] arr = new String[numRows];
for(int i = 0; i < arr.length; i ++) {
arr[i] = new String();
}
int row = 0, direction = 0;
for(int i = 0; i < s.length(); i ++) {
arr[row] += s.substring(i, i+1);
if(direction == 0 && row < numRows-1) {
row ++;
if(row == numRows - 1) {
direction =1;
}
}else if(direction == 1 && row>0) {
row -- ;
if(row == 0) {
direction = 0;
}
}
}
String ans = new String();
for(int i = 0; i < arr.length; i++) {
ans += arr[i];
}
return ans;
}
不模拟,数学规律
分析知道,第0行的第K+1字符下标是 2k(n-1);
最后一行对应2k(n-1)+n-1;
中间i行对应着 2k(n-1)+i 和2k(n-1)-i;
由此直接构造结果
public String convert(String s, int numRows) {
if(s == null || numRows <= 1) return s;
StringBuilder ans = new StringBuilder();
int k = 2 * numRows - 2;
for(int i = 0; i < numRows ; i ++) {
for(int j = 0; i + j < s.length(); j += k) {
ans.append(s.charAt(i + j));
if(i != 0 && i != numRows - 1 && j + k -i < s.length()) {
ans.append(s.charAt(j+k-i));
}
}
}
return ans.toString();
}