006. ZigZag-Conversion

difficulty: Medium

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 s, int numRows);

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P     I    N
A   L S  I G
Y A   H R
P     I

Example 3:

Input: s = "A", numRows = 1
Output: "A"

Constraints:

  • 1 <= s.length <= 1000

  • s consists of English letters (lower-case and upper-case), ',' and '.'.

  • 1 <= numRows <= 1000

Method One

class Solution {
    public String convert(String s, int numRows) {
        StringBuilder[] rows = new StringBuilder[numRows];
        for(int i = 0; i < numRows; i++){
            rows[i] = new StringBuilder();
        }
        // 这个做法就比较朴素。
        // 实际上有非常类似的写法。
        // 高明的地方就是用多个StringBuilder
        int curRow = 0;
        boolean isGoingDown = true;
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            rows[curRow].append(c);
            if(curRow == numRows - 1){
                isGoingDown = false;
            }
            if(curRow == 0){
                isGoingDown = true;
            }
            curRow = isGoingDown ? curRow + 1 : curRow - 1;
            if(curRow < 0){
                curRow = 0;
            }
            if(curRow >= numRows){
                curRow = numRows - 1;
            }
        }
        for(int i = 1; i < numRows; i++){
            rows[0].append(rows[i].toString());
        }
        return rows[0].toString();
    }
}

Method Two

class Solution {
    public String convert(String s, int numRows) {
        StringBuilder[] rows = new StringBuilder[numRows];
        for(int i = 0; i < numRows; i++){
            rows[i] = new StringBuilder();
        }
        int p = 0;
        // 这个方法看似爽,但是也很容易写错,一个稳妥的办法是,从上至下是完整的,而从下往上
        // 是从倒数第二行到第二行。 下面是错误的写法,虽然很对称,但是对 A,1 的输入TLE
        // while(p < s.length()){
        //     for(int i = 0; i < numRows - 1 && p < s.length(); i++){
        //         rows[i].append(s.charAt(p++));
        //     }
        //     for(int i = numRows - 1; i >= 1 && p < s.length(); i--){
        //         rows[i].append(s.charAt(p++));
        //     }
        // }
        while(p < s.length()){
            for(int i = 0; i < numRows && p < s.length(); i++){
                rows[i].append(s.charAt(p++));
            }
            for(int i = numRows - 2; i >= 1 && p < s.length(); i--){
                rows[i].append(s.charAt(p++));
            }
        }
        for(int i = 1; i < numRows; i++){
            rows[0].append(rows[i].toString());
        }
        return rows[0].toString();
    }
}

2023 年写的

我觉得2023年的写法比较好,很简洁,有spiral matrix的思想。用取余来切换一个循环的状态。

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1) return s;
        StringBuilder[] sbs = new StringBuilder[numRows];
        for (int i = 0; i < sbs.length; i++) {
            sbs[i] = new StringBuilder();
        }
        int[] directions = new int[]{1, -1};
        int curRow = 0;
        int curDirection = 0;
        for (int i = 0; i < s.length(); i++) {
            if (curRow < 0 || curRow >= numRows) {
                curRow -= directions[curDirection];
                curDirection = (curDirection + 1) % 2;
                curRow += directions[curDirection];
            }
            sbs[curRow].append(s.charAt(i));
            curRow += directions[curDirection];
        }
        String ans = "";
        for (int i = 0; i < numRows; i++) {
            ans += sbs[i].toString();
        }
        return ans;
    }
}

Last updated

Was this helpful?