# 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);
```

&#x20;

**Example 1:**

<pre><code><strong>Input: s = "PAYPALISHIRING", numRows = 3
</strong><strong>Output: "PAHNAPLSIIGYIR"
</strong></code></pre>

**Example 2:**

<pre><code><strong>Input: s = "PAYPALISHIRING", numRows = 4
</strong><strong>Output: "PINALSIGYAHRPI"
</strong><strong>Explanation:
</strong>P     I    N
A   L S  I G
Y A   H R
P     I
</code></pre>

**Example 3:**

<pre><code><strong>Input: s = "A", numRows = 1
</strong><strong>Output: "A"
</strong></code></pre>

&#x20;

**Constraints:**

* `1 <= s.length <= 1000`
* `s` consists of English letters (lower-case and upper-case), `','` and `'.'`.
* `1 <= numRows <= 1000`

## Method One

```Java
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

```java
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的思想。用取余来切换一个循环的状态。

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