6_ZigZag Conversion

[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);

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3

Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4

Output: "PINALSIGYAHRPI"

Explanation:

P     I    N
A   L S  I G
Y A   H R
P     I

Solution 1: slower

Idea:

  • For each row, loop over the input string once, and find the letters corresponding to right index, append to output.

Time Complexity: O(n)O(n) loop over each element in the input numRows times

Space Complexity: O(n)O(n)

def convert(s, numRows):
    """
    :type s: str
    :type numRows: int
    :rtype: str
    """
    if numRows == 1 or numRows >= len(s): return s

    output = []
    for i in range(numRows):
        for j in range(i, len(s)):
            length = 2*numRows-2
            if j%length == i or j%length == length-i:
                output.append(s[j])
    return "".join(output)

Solution 2: faster

Idea:

  • Initiate with an output array in which each element corresponds to one row.

  • Loop over each element in the string, with the direction. Direction goes down unless meet the last row.

Time Complexity: O(n)O(n) loop over each element in the input once

Space Complexity: O(n)O(n)

def convert(s, numRows):
    """
    :type s: str
    :type numRows: int
    :rtype: str
    """
    if numRows == 1 or numRows >= len(s):
        return s

    output = [''] * numRows
    row, direction = 0, 1

    for x in s:
        output[row] += x
        if row == 0:
            direction = 1
        elif row == numRows -1:
            direction = -1
        row += direction

    return ''.join(output)

Last updated