LeetCode編程6--ZigZag Conversion

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章