6. Zigzag Conversion - Explanation
Description
You are given a string s and a positive integer numRows. Return the string after converting it to zig-zag pattern.
The string "GOOGLEISHIRING" is written in a zigzag pattern on a given number of rows numRows=3 like this: (you may want to display this pattern in a fixed font for better legibility)
G L H N
O G E S I I G
O I RAnd then read line by line: "GLHNOGESIIGOIR"
Example 1:
Input: s = "GOOGLEISHIRING", numRows = 4
Output: "GINOESIGOLHRGI"Explanation:
G I N
O E S I G
O L H R
G IExample 2:
Input: s = "GOOGLEISHIRING", numRows = 5
Output: "GHOSIOIRGEIGLN"Explanation:
G H
O S I
O I R
G E I G
L NConstraints:
1 <= s.length, numRows <= 1000sconsists of English letters (lower-case and upper-case),','and'.'.
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- String Manipulation - Building strings from characters and concatenating multiple strings
- Pattern Recognition - Identifying mathematical formulas to calculate character positions in repeating patterns
- Array/List Operations - Using multiple lists to collect characters row by row
1. Iteration - I
Intuition
When writing characters in a zigzag pattern, each row follows a predictable spacing pattern. The key insight is that the distance between characters in the same row follows a cycle of length 2 * (numRows - 1). For the first and last rows, characters appear at regular intervals of this cycle length. For middle rows, there are two characters per cycle: one at the regular position and one at a calculated offset within the cycle.
Algorithm
- Handle the edge case where
numRowsis 1 by returning the original string. - Calculate the base
incrementas2 * (numRows - 1), which represents one full zigzag cycle. - For each row
rfrom0tonumRows - 1:- Start at index
rand jump by theincrementto collect characters at regular cycle positions. - For middle rows (not first or last), also collect the "diagonal" character at position
i + increment - 2 * rif it exists.
- Start at index
- Concatenate all collected characters and return the result.
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1:
return s
res = []
for r in range(numRows):
increment = 2 * (numRows - 1)
for i in range(r, len(s), increment):
res.append(s[i])
if r > 0 and r < numRows - 1 and i + increment - 2 * r < len(s):
res.append(s[i + increment - 2 * r])
return ''.join(res)Time & Space Complexity
- Time complexity:
- Space complexity: for the ouput string.
2. Iteration - II
Intuition
Instead of calculating positions mathematically, we can simulate the actual zigzag writing process. We maintain a current row and a direction. As we traverse the string, we place each character in its corresponding row. When we hit the top or bottom row, we reverse direction. This approach directly models how characters would be written in the zigzag pattern.
Algorithm
- Handle edge cases where
numRowsis 1 or greater than or equal to the string length by returning the original string. - Create an array of lists (or strings), one for each
row. - Initialize the current
rowto0anddirectionto1(moving down). - For each character in the string:
- Append the character to the current row's list.
- Move to the next row by adding the
direction. - If we reach the first or last row, reverse the
directionby multiplying by-1.
- Concatenate all rows in order and return the result.
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1 or numRows >= len(s):
return s
res = [[] for _ in range(numRows)]
row, dir = 0, 1
for c in s:
res[row].append(c)
row += dir
if row == 0 or row == (numRows - 1):
dir *= -1
return ''.join([''.join(row) for row in res])Time & Space Complexity
- Time complexity:
- Space complexity: for the output string.
Common Pitfalls
Not Handling the Single Row Edge Case
When numRows == 1, the zigzag pattern is just the original string. Without this check, the increment becomes 2 * (1 - 1) = 0, causing an infinite loop or division issues.
# Wrong: Missing edge case
increment = 2 * (numRows - 1) # increment = 0 when numRows = 1
for i in range(r, len(s), increment): # Infinite loop!Incorrect Direction Toggle Logic
When simulating the zigzag traversal, the direction should only flip when reaching the first or last row. A common mistake is toggling direction after every step, or only checking one boundary.
# Wrong: Toggling every time or only checking one boundary
row += dir
if row == numRows - 1: # Misses the top boundary!
dir *= -1Wrong Index Calculation for Middle Row Diagonal Characters
In the mathematical approach, middle rows have two characters per cycle. The diagonal character position i + increment - 2 * r is often miscalculated, leading to missing characters or index out of bounds errors.
# Wrong: Using incorrect offset formula
if r > 0 and r < numRows - 1:
res.append(s[i + increment - r]) # Should be: i + increment - 2 * r
Sign in to join the discussion