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;
}
}