LeetCode ZigZag helper function code The string &quot;PAYPALISHIRING&quot; 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: &quot;PAHNAPLSIIGYIR&quot;
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);



I used a helper function approach after realizing that the &quot;Grid&quot; needs to be updated in the same manner over and over again

I have received feedback that storing a grid may take too much memory

Would a &quot;mathematical&quot; approach actually be more readable? And would it be something that can be though of within 20ish minutes (interview time)

I have many if statements that are used to exit out of loops to avoid array index errors


Any feedback or criticism is appreciated - nitpick on anything that seems off

glaring issue is that this doesn't handle edge cases well. For example: &quot;A 2&quot;

https://leetcode.com/problems/zigzag-conversion/
class Solution:
    def convert(self, s: str, numRows: int) -&gt; str:
        if numRows == 1:
            return s
        row = [''] * (len(s) // 2)
        self.s = s
        self.numRows = numRows
        self.final_grid = []

        for i in range(numRows):
            self.final_grid.append(list(row))

        self.addElements(0, 0)

        return &quot;&quot;.join(map(&quot;&quot;.join, self.final_grid))


    def addElements(self, count, column):
        print(column, &quot;beg&quot;)
        for i in range(self.numRows):
            if count &gt; len(self.s) - 1:
                break
            self.final_grid[i][column] = self.s[count]
            count += 1

        for i in range(1, self.numRows - 1):
            if count &gt; len(self.s) - 1:
                break

            self.final_grid[self.numRows - i - 1][column + i] = self.s[count]
            count += 1
            print(column, &quot;end&quot;)
            print(column + self.numRows - 1)
        
        if count &lt; len(self.s) - 1:
            self.addElements(count, (column + self.numRows - 1))
As you pointed out, you don't actually need to lay the characters out into a grid.  It would be more efficient to use arithmetic to figure out the indexes of the characters in each row.

For example, if num_rows is 3, then each down-up cycle will consist of 4 characters.  (zigzag_size = 2 * num_rows - 2).  Then we also know that the top of each zigzag will consist of indexes 0, 4, 8, 12, … of the string (for z in range(0, len(s), zigzag_size)).

The middle row will consist of indexes z+1 and z+3.  The bottom row will consist of indexes z+2.  The zigzag_indexes() generator generalizes those calculations for any numRows.

import math

def zigzag_indexes(num_rows):
    yield (0, math.inf)                             # Top of each zigzag
    yield from zip(
        range(1, num_rows),                         # Downward
        range(2 * num_rows - 3, num_rows - 1, -1)   # Upward
    )
    yield (num_rows - 1, math.inf)                  # Bottom of each zigzag

def convert(s, num_rows):
    if num_rows == 1:
        return s
    zigzag_size = 2 * num_rows - 2
    return ''.join(
        (s[z+a] if z+a &lt; len(s) else '') + (s[z+b] if z+b &lt; len(s) else '')
        for a, b in zigzag_indexes(num_rows)
        for z in range(0, len(s), zigzag_size)
    )

print(convert('PAYPALISHIRING', 3))