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".
Hide Tags: String
解题思路:
因为行数为变量,因此我们需要找到每一行的规律。例如:当行数numRows=4时,则ZigZag应该按下列方式排列
不难看出,满数为4的列之间的步数为4,实际上,此时步的规律为:step=2*numRows-2 =2*4-2=6
0 6 12 18
1 5 7 11 13 17 19
2 4 8 10 14 16 20
3 9 15 21
接着我们看非满数的列,不难看出此类列的每一行都只有一个数,就拿第二例为例:1 5 7 11 13 17 19,先看看
1 5 7 ,“1”与“5”之间的步数为:step1=(numRows-1-1)*2=(4-1-1)*2=4 ,而“5”与“7”之间的步数为:step2=step-step1=6-4=2.
不难看出:假设我们所在的行为第i行(i<numRows) step=2*numRows-2 ,step1=(numRows-1-i)*2,step2=step-step1
我们所找到的规律并不适合numRows=1的情况,因此需要将它单独拿出来套路
代码如下:
public static String convert(String s,int numRows) { //当字符串的长度为0或行数为1时,直接返回s if (s.length()==0||numRows==1) { return s; } //new一个StringBuilder,用于 字符串的拼凑 StringBuilder sb=new StringBuilder(); int step=2*numRows-2; for (int i = 0; i < numRows; i++) { //第一行与最后一行,中间的步数为:step=2*numRows-2 if (i==0||i==numRows-1) { for (int j = i; j < s.length(); j=j+step) { sb.append(s.charAt(j)); } } else { int j=i; //设置一个step1与step2交替变换的标识 boolean flag=true; int step1=2*(numRows-1-i); int step2=step-step1; while (j<s.length()) { sb.append(s.charAt(j)); if (flag) { j=j+step1; } else { j=j+step2; } flag=!flag; } } } //将StringBuilder转换成String类型 return sb.toString(); }