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"
大概题意:输入一个字符串以及要求的矩阵行数,求字符串拆分成字符后按照zigzag格式排列,再读取每一行拼接成的字符串。
所谓的zigzag格式,有点类似锯齿波,为了找出规律,我们列举几组出来看看,字符串的内容替换成字符数组的下标,方便写程序,如下:
nRows=1
zigzag pattern: 0 1 2 3 4 5 6 7 ........
nRows=2
zigzag pattern:
0 2 4 6 8 ......
1 3 5 7 9 ......
nRows=3
zigzag pattern:
0 4 8 12
1 3 5 7 9 11 13 ......
2 6 10 14
nRows=4
zigzag pattern:
0 6 12
1 5 7 11 13 ......
2 4 8 10 14
3 9 15
nRows=5
zigzag pattern:
0 8 16
1 7 9 15 17
2 6 10 14 18 ......
3 5 11 13 19
4 12 20
通过列出以上形式,可以总结出其中的规律:
1.nRows=1时是特殊情况,直接返回,以下下都是nRows>1的规律(默认行数是正整数)
2.无论nRows是多少,首行和尾行构成等差数列切差值一样,每一步差值step为(nRows-1)*2
3.当nRows为奇数时,中间那一行为等差数列,每一步差值step为nRows-1
4.除去首行尾行,以及奇数的中间行,剩下的行首位不完全对称,比如nRows=2时,第2行和第3行不完全对称,比如nRows=5时,第2行和第4行不完全对称
5.上一条规律中的所谓不完全对称是指:每一行不是等差数列,但是有两个固定的差值step1和step2,且对称行的差值对调,比如nRows=5时,第2行的step1=6,step2=2,对称的第4行step1=2,step2=6
最后写出跑通的JAVA代码如下:
public class ZigzagSolution {
public static void main(String args[]){
System.out.println(convert("skdf",2));
}
public static String convert(String s, int numRows) {
//检查字符串的值
if(s == null){
return null;
}
//numRows=1的情况,直接输出字符串
if(1 == numRows){
return s;
}
//拆分成字符串
char[] buf = s.toCharArray();
int len = buf.length;
//使用StringBuilder数组来储存结果,每一个StringBuilder接收一行的结果
StringBuilder[] builders = new StringBuilder[numRows];
for(int i=0; i < builders.length; i++){
builders[i] = new StringBuilder();
}
for(int i=0; i <= numRows/2; i++){//因为对称的关系,不用循环完全
//首尾构成等差数列的情况
if(0 == i){
//首部
int tmp = i;//tmp为每个对应字符的下标
int step = (numRows-1)*2;//步差
while(tmp < len){
builders[i].append(buf[tmp]);
tmp += step;
}
//尾部,首位不在同一个循环里,元素个数不一定一样
tmp = numRows-1-i;
int j = tmp;
while(tmp < len){
builders[j].append(buf[tmp]);
tmp += step;
}
}else if( (numRows%2)!=0 && i==(numRows/2)){//numRows为奇数,中间那行为等差数列
int tmp = i;
int step = numRows - 1;//步差
while(tmp < len){
builders[i].append(buf[tmp]);
tmp += step;
}
}else if(i < numRows/2){//其他对称的情况
int tmp =i;
int step1 = (numRows-2)*2 -(i-1)*2; //第一个步差
int step2 = 2*i; //第二个步差
boolean flag = true;
while(tmp < len){
builders[i].append(buf[tmp]);
if(flag){ //步差交替
tmp += step1;
flag = !flag;
}else{
tmp += step2;
flag = !flag;
}
}
tmp = numRows-1-i; //对称的另一行
int j = tmp;
flag = true;
while(tmp < len){
builders[j].append(buf[tmp]);
if(flag){
tmp += step2;
flag = !flag;
}else{
tmp += step1;
flag = !flag;
}
}
}else{
break;
}
}
String result = "";
for(int i=0; i < numRows; i++){
result += builders[i].toString();
}
return result;
}
}