问题:
The string "PAYPALISHIRING"
is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N A P L S I I G Y I R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3)
should return "PAHNAPLSIIGYIR"
.
解决:
【注】题目要求将输入字符以倒立的之字形表示出来。传入的参数包括字符串以及之字形可以有几行。本题的关键是计算各个字符的位置,需要计算出推导公式。
① 每一行对应一个字符串,遍历原字符串,然后把相应的字符加到对应行的字符串中。
class Solution { //82ms
public String convert(String s, int numRows) {
int len = s.length();
if(numRows <= 1 || numRows >= len) return s;//不用转换
String[] tmp = new String[numRows];
Arrays.fill(tmp,"");//必须加,否则有null
int flag = 1;//1表示向下 -1表示向上
int row = 0;
for (int i = 0;i < len ;i ++ ) {
tmp[row] += s.charAt(i);
row += flag;
if(row >= numRows){
row = numRows - 2;
flag = -1;
}
if(row < 0){
row = 1;
flag = 1;
}
}
String res ="";
for (int i = 0;i < numRows ;i ++ ) {
res += tmp[i];
}
return res;
}
}
② 本题想要考的是找规律:
所有行的重复周期是2 * numRows - 2;
对于首行和末行之间的行,还会额外重复一次,重复的这一次距离本周期起始字符的距离是 2 * numRows - 2 - 2 * i。
public class Solution { //89ms
public String convert(String s, int numRows) {
int len = s.length();
if (len == 0 || numRows < 2) return s;
String res = "";
int lag = 2 * numRows - 2; //循环周期
for (int i = 0; i < numRows; i ++) {
for (int j = i; j < len; j += lag) {
res += s.charAt(j);
//非首行和末行时还要加一个
if (i > 0 && i < numRows-1) {
int t = j + lag - 2*i;
if (t < len) {
res += s.charAt(t);
}
}
}
}
return res;
}
}
③ 方法②的进化版
public class Solution { // 44ms
public String convert(String s, int numRows) {
int len = s.length();
if (len <= numRows || numRows == 1) return s;
char[] res = new char[len];
int lag = 2 * (numRows - 1);
int index = 0;
for (int i = 0; i < numRows; i++){
int inter = lag - 2 * i;
for (int j = i; j < len; j += lag){
res[index] = s.charAt(j);
index ++;
if (inter < lag && inter > 0 && j + inter < len && index < len){
res[index] = s.charAt(j + inter);
index ++;
}
}
}
return new String(res);
}
}