LeetCode Question 6: Zigzag transformation (Python3 solution)

1: Problem description

Source: LeetCode

Difficulty: Moderate


Details of the problem:
Arrange a given string in a zigzag from top to bottom and from left to right saccording to thenumRows given number of lines .

For example, when the input string is "PAYPALISHIRING" and the number of lines is 3, the arrangement is as follows:

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

After that, your output needs to be read line by line from left to right to produce a new string, for example: "PAHNAPLSIIGYIR".


2: Problem analysis

2.1 Time Complexity and Space Complexity

Before actually starting to introduce various algorithms, first show their respective time complexity and space complexity in tabular form, nnn represents the stringsslength of s .

algorithm time complexity space complexity
two-dimensional matrix O ( n u m R o w s × n ) O(numRows×n) O(numRows×n) O ( n u m R o w s × n ) O(numRows×n)O(numRows×n)
2D Matrix Improvements O( n n n) O ( n ) O(n)O ( n )
construction method O ( n ) O(n)O ( n ) O(1) O(1)O(1)

2.2 Two-dimensional matrix

Use the two-dimensional matrix to store in the two-dimensional array in the order as in Section 1, and replace the characters without an empty string. The elements in the vertical line are continuously increasing rows, and the columns remain unchanged; the elements in the diagonal line are successively decreasing rows and increasing columns;

2.2.1 Construction matrix

First analyze that the string is written in a zigzag, and there are several columns in total.
insert image description here

We take the inverted N-shaped vertical line and the elements on the slash as a unit. The number of elements on the vertical line = num R ows numRowsn u m R o w s ; the number of elements on the slash isnum R ows − 2 numRows-2numRows2 ; so the total number of elements in a cell isr = num Rows × 2 − 2 r=numRows×2-2r=numRows×22 ; The number of columns in each unit:1 + num R ows − 2 = num R ows − 1 1+numRows-2=numRows-11+numRows2=numRows1

Then there are ⌊ nr ⌋ \lfloor \dfrac{n}{r}\rfloorrn units, and the number of elements that cannot form a unit also depends on whether> num R ows > numRows> n u m R o w s . If less than, the remaining elements form a column (because a vertical bar hasnum R ows numRowsn u m R o w s elements); if greater than numRows (that is, the slash part), each element occupies an exclusive column.

Return the default value:
col = ⌊ nr ⌋ × ( num R ows − 1 ) re = n % rcol 1 = ⌊ renum R ows ⌋ + re % num R owscol = col + col 1 \begin{aligned} &col =\lfloor \dfrac{n}{r}\rfloor ×(numRows-1) \\ &re=n\% r\\ &col1=\lfloor \dfrac{re}{numRows}\rfloor +re \% numRows\\ &col = col + col1 \end{aligned}col=rn×(numRows1)re=n%rco l 1=numRowsre+re%numRowscol=col+co l 1

And the number of rows of this matrix is ​​num R ows numRowsn u m R o w s .
So the matrix has dimensions( num R ows , col ) (numRows,col)(numRows,col)。‘

The official solution is to choose a lazy method, so that those who do not form a unit can form a unit by filling in the blanks. Such a solution requires ⌈ nr ⌉ \lceil \dfrac{n}{r}\rceilrnThe ⌉ column is rounded up. Although the code is simpler in this way, it will take up more space than my solution.

2.2.2 Judging the position

In order to judge whether the current element is on a vertical line or a diagonal line, we need to build a judgment criterion.

The official solution has been mentioned earlier, through the index index index of the current character in the stringin d e x to the number of elements rrof a unitR finds the remainder, and the remainder is less thannum R ows numRowsn u m R o w s means it is on the vertical line; if it is greater than or equal to numRows, it means it is on the slash line;

My solution is:

  • set a flag flagf l a g , the default isF alse FalseFalse
  • if row number i = 0 i=0i=0时,flag = False flag=Falseflag=F a l se , indicating that the vertical bar will be entered
  • i = n u m R o w s − 1 i=numRows-1 i=numRows1时, f l a g = T r u e flag=True flag=T r u e , indicating that the next element will enter the slash
  • if flag = False flag=Falseflag=F a l se , number of linesi + = 1 i+=1i+=1 , the number of columnsjjj stays the same
  • 如果 f l a g = T r u e flag=True flag=T r u e , row numberi − = 1 i-=1i=1 , the number of columnsj + = 1 j+=1j+=1

2.2.3 Boundaries

The boundary problem of this problem is that there is only one row or one column state after conversion. When there is only one row, that is num R ows = 1 numRows=1numRows=1 ; if there is only one column, that isnumRows >= n numRows >= nnumRows>=n;

2.2.4 Code

def convert(s: str, numRows: int) -> str:
    length = len(s)
    # 计算一共占了多少列
    # 当排列后为一行或者一列的情况,则直接返回原字符串
    if length <= numRows or numRows == 1:
        return s
    else:
        # 以Z字形中的一个横线和对角线为一个单元,计算s中能有多少个这样的单元
        t = length // (numRows + numRows - 2)
        temp = length % (numRows + numRows - 2)
        col1 = temp // numRows
        col1 += temp % numRows
        # 一个单元占了 (numRows-2 + 1)列,而剩下的不成单元的占col1列
        col = (numRows - 2 + 1) * t + col1
    # 先创建一个空字符列表,一共numRows行col列
    result = [[""] * col for i in range(numRows)]
    index = 0
    i = 0  # 第几行
    j = 0  # 第几列
    diag = False  # 表示是否在对角线上
    # 通过分析,可以得知当行标走到numRows-1时,下一步就要走到对角线处了,此时行不断往上,列不断往右
    # 当行标再次回到0的时候,就是走出了对角线,此时行不断往下,列保持不变
    while index <= length - 1:
        if i == 0:
            diag = False
        if i == numRows - 1:
            diag = True
        result[i][j] = s[index]
        index += 1
        if not diag:
            i += 1
        else:
            i -= 1
            j += 1

    result_2 = ''
    for row_item in result:
        for col_item in row_item:
            if col_item != '':
                result_2 += col_item

    return result_2

For time complexity, create and traverse result resultThe consumption of res u lt is higher, which isO (number of rows×number of columns) O(number of rows×number of columns)O ( number of lines×number of columns ) , number of rows= num R ows =numRows=n u m R o w s , the number of columns can be roughly regarded asO ( n ) O(n)O ( n ) , the time complexity isO ( num R ows × n ) O(numRows×n)O(numRows×n) w h i l e while w hi l e internal time complexity isO ( n ) O(n)O ( n ) , so the total time complexity isO ( num R ows × n ) O(numRows×n)O(numRows×n)

The space complexity is also O ( num R ows × n ) O(numRows×n)O(numRows×n)

2.3 Improved two-dimensional matrix

The above-mentioned two-dimensional matrix has a lot of gaps, wasting a lot of space.

So we can treat each row as a list, and every time we move to that row, add the element to the list corresponding to this row. The rest are the same as the first solution.

2.3.1 Code

def convert2(s: str, numRows: int) -> str:
    """使用多个空白列表存储每一行的字符"""
    length = len(s)
    if length <= numRows or numRows == 1:
        return s
    else:
        # 生成一个numRows行的列表存储每一行的字符
        result = [[] for i in range(numRows)]
        i = 0  # 表示行
        diag = False
        for item in s:
            result[i].append(item)
            if i == 0:
                diag = False
            elif i == numRows - 1:
                diag = True
            if diag:
                i -= 1
            else:
                i += 1

    from itertools import chain
    return ''.join(chain(*result))

For time complexity, while whileBoth w hi l e and list creation and traversal time complexity areO ( n ) O(n)O ( n ) , so the time complexity of the algorithm isO ( n ) O(n)O ( n )

For space complexity, all strings are stored in the list, space complexity O ( n ) O(n)O ( n )

2.4 Construction method

We can directly explore which line a certain subscript character should be placed in.
|column 0|column 1| ...|column t-1|column t| --|--|---|---|---|--|**0 row**| | | || **1 row**| | | | | **2 rows**| | | | |
As shown in the figure above, suppose num R ows = 4 numRows=4numRows=4.

Here t = rt=rt=r (referred to in Section 2.2.1, the number of elements per cell).

  1. We can find that in each unit ( note, each unit is mentioned here, not a row in this table ), the element subscript of row 0 is ttInteger multiples of t , that is, xt xtx t d form
  2. The subscript of the element in the last row of each cell should be of the form xt + num R ows − 1 xt+numRows-1xt+numRows1
  3. Each unit of these rows in the middle has two elements, the first element is the same as the element in the last row, and only needs to satisfy the subscript to conform to the form xt + i xt+ixt+i , is at theiirow i ; while the second element satisfies( xt + t − i ) (xt + t - i)(xt+ti ) in the form;
  4. Let's unify the above situation, the subscript of the first element of all rows is consistent with xt + i xt+ixt+i的形式;
    0 < i < n u m R o w s − 1 0<i<numRows-1 0<i<numRows1 , the subscript of its second element satisfies( xt + t − i ) (xt + t - i)(xt+ti ) in the form

2.4.1 Code

where jjj is the value0 t , 1 t , 2 t , 3 t . . . 0t, 1t,2t,3t...0 t ,1t,2 t ,3 sequences of t ... ; andiii displayiiLine i , remind again that r = tr=therer=t.

def convert4(s: str, numRows: int) -> str:
    """在方法1的基础上,分析字符串下标对应二维数组索引"""
    length = len(s)
    if length <= numRows or numRows == 1:
        return s
    else:

        ans = []
        r = 2 * numRows - 2  # 一个单元拥有的字符数
        for i in range(numRows):
            # 因为每一行最少有一个元素,因此-i,可以避免i与j相加后下标越界
            # j = 0r, 1r, 2r, 3r,  s.t. j < length-i
            for j in range(0, length - i, r):
                # 添加每个单元中竖线中的元素
                # j + i:
                # 第0行元素下标,0r+0, 1r+0,2r+0
                # 第1行元素下标,0r+1, 1r+1, 2r+1
                # 第i行元素下标,j+i
                ans.append(s[j + i])  # 第一个元素
                # 因为斜线中的元素下标为
                # 第0行没有斜线
                # 第1行元素下标,1r-1, 2r-1
                # 第i行元素下标,j+r-i
                if 0 < i < numRows - 1 and j + r - i < length:
                    ans.append(s[j + r - i])  # 第二个元素

    return ''.join(ans)

For time complexity, all the elements in the string are added to the list, so the time complexity is O ( n ) O(n)O ( n ) ;

For space complexity, ans is the return value, which is not included in the statistics of space complexity, so the space complexity is O(1).

Guess you like

Origin blog.csdn.net/weixin_43490422/article/details/126513310