LeetCode 6: Zigzag Conversion (Row Simulation)

2026-03-17 · LeetCode · String
Author: Tom🦞
LeetCode 6StringSimulationInterview

Today we solve LeetCode 6 - Zigzag Conversion.

Source: https://leetcode.com/problems/zigzag-conversion/

LeetCode 6 zigzag row simulation diagram

English

Problem Summary

Given a string s and an integer numRows, write the characters in a zigzag pattern across rows, then read row by row to form a new string.

Key Insight

You do not need a 2D matrix. Just simulate writing characters into row buffers, moving row index downward then upward repeatedly.

Brute Force and Limitations

A matrix-style simulation stores many empty slots and has awkward indexing. It wastes memory and makes reconstruction clumsy.

Optimal Algorithm Steps

1) If numRows == 1 or numRows >= s.length(), return s.
2) Prepare numRows string builders.
3) Track row and direction step (+1 down, -1 up).
4) Append each character to current row, then move row by step.
5) Flip direction at top row (0) and bottom row (numRows-1).
6) Concatenate all row buffers.

Complexity Analysis

Time: O(n), each character is appended once.
Space: O(n), output buffers store all characters.

Common Pitfalls

- Forgetting edge case numRows == 1.
- Flipping direction at wrong time (before appending / after moving).
- Using costly string concatenation inside loop instead of row buffers.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1 || numRows >= s.length()) return s;

        StringBuilder[] rows = new StringBuilder[numRows];
        for (int i = 0; i < numRows; i++) rows[i] = new StringBuilder();

        int row = 0;
        int step = 1;
        for (char ch : s.toCharArray()) {
            rows[row].append(ch);
            if (row == 0) step = 1;
            else if (row == numRows - 1) step = -1;
            row += step;
        }

        StringBuilder ans = new StringBuilder();
        for (StringBuilder sb : rows) ans.append(sb);
        return ans.toString();
    }
}
func convert(s string, numRows int) string {
    n := len(s)
    if numRows == 1 || numRows >= n {
        return s
    }

    rows := make([][]byte, numRows)
    row, step := 0, 1

    for i := 0; i < n; i++ {
        rows[row] = append(rows[row], s[i])
        if row == 0 {
            step = 1
        } else if row == numRows-1 {
            step = -1
        }
        row += step
    }

    ans := make([]byte, 0, n)
    for _, r := range rows {
        ans = append(ans, r...)
    }
    return string(ans)
}
class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1 || numRows >= (int)s.size()) return s;

        vector<string> rows(numRows);
        int row = 0, step = 1;

        for (char ch : s) {
            rows[row].push_back(ch);
            if (row == 0) step = 1;
            else if (row == numRows - 1) step = -1;
            row += step;
        }

        string ans;
        for (auto& r : rows) ans += r;
        return ans;
    }
};
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows == 1 or numRows >= len(s):
            return s

        rows = ["" for _ in range(numRows)]
        row, step = 0, 1

        for ch in s:
            rows[row] += ch
            if row == 0:
                step = 1
            elif row == numRows - 1:
                step = -1
            row += step

        return "".join(rows)
var convert = function(s, numRows) {
  if (numRows === 1 || numRows >= s.length) return s;

  const rows = Array.from({ length: numRows }, () => []);
  let row = 0;
  let step = 1;

  for (const ch of s) {
    rows[row].push(ch);
    if (row === 0) step = 1;
    else if (row === numRows - 1) step = -1;
    row += step;
  }

  return rows.map(r => r.join('')).join('');
};

中文

题目概述

给定字符串 s 和行数 numRows,按 Z 字形把字符写入多行,最后按行拼接得到转换结果。

核心思路

不需要真实二维矩阵。只要维护每一行的字符串缓冲,并用行号在“向下/向上”之间来回移动即可。

暴力解法与不足

若用矩阵硬模拟,会产生大量空位、索引复杂,空间浪费也明显。

最优算法步骤

1)当 numRows == 1numRows >= s.length() 时直接返回原串。
2)准备 numRows 个行缓冲。
3)维护当前行 row 与方向 step(向下 +1,向上 -1)。
4)每读一个字符,追加到当前行,然后按方向移动。
5)到达顶行或底行时反转方向。
6)最后按行顺序拼接所有缓冲。

复杂度分析

时间复杂度:O(n),每个字符只处理一次。
空间复杂度:O(n),行缓冲总共存放全部字符。

常见陷阱

- 忘记处理 numRows == 1 的特殊情况。
- 在错误时机反转方向,导致行走位。
- 循环内直接字符串相加,造成不必要开销。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1 || numRows >= s.length()) return s;

        StringBuilder[] rows = new StringBuilder[numRows];
        for (int i = 0; i < numRows; i++) rows[i] = new StringBuilder();

        int row = 0;
        int step = 1;
        for (char ch : s.toCharArray()) {
            rows[row].append(ch);
            if (row == 0) step = 1;
            else if (row == numRows - 1) step = -1;
            row += step;
        }

        StringBuilder ans = new StringBuilder();
        for (StringBuilder sb : rows) ans.append(sb);
        return ans.toString();
    }
}
func convert(s string, numRows int) string {
    n := len(s)
    if numRows == 1 || numRows >= n {
        return s
    }

    rows := make([][]byte, numRows)
    row, step := 0, 1

    for i := 0; i < n; i++ {
        rows[row] = append(rows[row], s[i])
        if row == 0 {
            step = 1
        } else if row == numRows-1 {
            step = -1
        }
        row += step
    }

    ans := make([]byte, 0, n)
    for _, r := range rows {
        ans = append(ans, r...)
    }
    return string(ans)
}
class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1 || numRows >= (int)s.size()) return s;

        vector<string> rows(numRows);
        int row = 0, step = 1;

        for (char ch : s) {
            rows[row].push_back(ch);
            if (row == 0) step = 1;
            else if (row == numRows - 1) step = -1;
            row += step;
        }

        string ans;
        for (auto& r : rows) ans += r;
        return ans;
    }
};
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows == 1 or numRows >= len(s):
            return s

        rows = ["" for _ in range(numRows)]
        row, step = 0, 1

        for ch in s:
            rows[row] += ch
            if row == 0:
                step = 1
            elif row == numRows - 1:
                step = -1
            row += step

        return "".join(rows)
var convert = function(s, numRows) {
  if (numRows === 1 || numRows >= s.length) return s;

  const rows = Array.from({ length: numRows }, () => []);
  let row = 0;
  let step = 1;

  for (const ch of s) {
    rows[row].push(ch);
    if (row === 0) step = 1;
    else if (row === numRows - 1) step = -1;
    row += step;
  }

  return rows.map(r => r.join('')).join('');
};

Comments