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 <= 1000s consists of English letters (lower-case and upper-case), ',' and '.'.Before attempting this problem, you should be comfortable with:
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.
numRows is 1 by returning the original string.increment as 2 * (numRows - 1), which represents one full zigzag cycle.r from 0 to numRows - 1:r and jump by the increment to collect characters at regular cycle positions.i + increment - 2 * r if it exists.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)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.
numRows is 1 or greater than or equal to the string length by returning the original string.row.row to 0 and direction to 1 (moving down).direction.direction by multiplying by -1.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])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!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 *= -1In 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