给一个String: "PAYPALISHIRING"
要求按竖Z字方法去排列再横向读出,给定行数R。
若 R = 3:
P   A   H   N
A P L S I I G
Y   I   R
则程序输出应为 :"PAHNAPLSIIGYIR"
若R = 4 :
P     I    N
A   L S  I G
Y A   H R
P     I
程序输出应为 : "PINALSIGYAHRPI"

分析:找规律,将每行当作一个研究对象,找出每个字母在原字符串中index的代数规律。
找规律最简单的方法就是多举几个例子,其实就是高中数学题中找数组的规律。

本题的规律:
/*R=numRows
d=2R-2    1                           2R-1                         4R-3
d=        2                     2R-2  2R                    4R-4   4R-2
d=        3               2R-3        2R+1              4R-5       .
d=        .           .               .               .            .
d=        .       R+2                 .           3R               .
d=        R-1 R+1                     3R-3    3R-1                 5R-5
d=2R-2    R                           3R-2                         5R-4
*/
假设当前行数是r,总行数R,I(n)表示某行第n个字母在原字符串中的index,n从0开始:

    r=1或R时:I(n+1) = I(n)+2*(R-1)
    1<r<R时:
    I(n+1)=I(n)+2*(R-r),n为偶数
    I(n+1)=I(n)+2*(r-1),n为奇数

public static String convert(String s, int numRows) {
    if(s == null || s.length() == 0 || numRows ==1 || numRows >= s.length())
        return s;

    StringBuilder myString = new StringBuilder();
    
    //第1行
    for(int i = 1; i < s.length()+1;i+=2*(numRows-1))
        myString.append(s.charAt(i-1));
    //中间
    for(int i = 2; i < numRows;i++) {
        boolean k=true;
        for(int j = i; j < s.length()+1;j+= (k) ? 2*(numRows-i) : 2*(i-1),k=!k)
            myString.append(s.charAt(j-1));

    }
    //第R行
    for(int i = numRows;i<s.length()+1;i+=2*(numRows-1))
        myString.append(s.charAt(i-1));

    return myString.toString();

}

讨论: 这代码不快(32%),如果用String而不是StringBuilder会更慢大约两倍,
优点在于书写简单逻辑清晰,如果面试碰到,这样的代码应该够了。

若文章中有错误或者各路大神有更好解法,欢迎评论。

Ref: If you are confused with zigzag pattern,come and see!


KirkBai
27 声望6 粉丝