Loading

Leetcode - 6. Z 字形变换

将一个给定字符串s根据给定的行数numRows,以从上往下、从左到右进行Z字形排列。
比如输入字符串为"PAYPALISHIRING"行数为3时,排列如下:

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

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

示例 1:

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例 2:

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

示例 3:

输入:s = "A", numRows = 1
输出:"A"

提示:

1 <= s.length <= 1000
s 由英文字母(小写和大写)、',' 和 '.' 组成
1 <= numRows <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zigzag-conversion
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解1 2021/8/24 O(n2)

from datetime import datetime
import numpy as np

def convert(s: str, numRows: int) -> str:
    # P   A   H   N
    # A P L S I I G
    # Y   I   R
    ### 错误 - 1
    # 处理掉简单的情况,下面的while处理不了单行的情况
    if numRows==1 or numRows==s.__len__(): return s
    ### 错误 - 1
    ### 超时 - 1
    # msize=1000
    # numRows=2/3的情况,msize都是500,修改为500
    ### 错误 - 2
    # msize = 500
    # 只考虑了列,没有考虑行,比如numRows=503,就崩了
    msize=1000
    ### 错误 - 2
    ### 超时 - 1
    len=s.__len__()
    m=np.zeros(shape=(msize,msize),dtype=str)
    x=y=0
    curr=0
    # 方向,-1:向下;1:向上
    dir=-1
    # O(n)
    while curr<len:
        m[x][y]=s[curr]
        curr+=1
        if dir==-1:
            if x<numRows-1:
                x+=1
            else:
                x-=1
                y+=1
                dir=-dir
        else:
            if x>0:
                x-=1
                y+=1
            else:
                x+=1
                dir=-dir
    # print(m)
    # 以下的表达是错误的:
    # print(''.join(m[x] for x in range(0,msize)))

    # O(n^2)
    res=''
    for x in range(0,msize):
        ### 超时 - 2
        if m[x][0]=='': break
        ### 超时 - 2
        res+=''.join(m[x])
    return res

if __name__ == '__main__':
    print(convert("PAYPALISHIRING",3))
    print(convert("PAYPALISHIRING",4))
    print(convert("A",1))

    ### 错误
    # 1
    print(convert("ABC",1))
    print(convert("ABC",3))
    # 2
    print(convert("hjouvsuyoypayulyeimuotehzriicfskpggkbbipzzrzucxamludfykgruowzgiooobppleqlwphapjnadqhdcnvwdtxjbmyppphauxnspusgdhiixqmbfjxjcvudjsuyibyebmwsiqyoygyxymzevypzvjegebeocfuftsxdixtigsieehkchzdflilrjqfnxztqrsvbspkyhsenbppkqtpddbuotbbqcwivrfxjujjddntgeiqvdgaijvwcyaubwewpjvygehljxepbpiwuqzdzubdubzvafspqpqwuzifwovyddwyvvburczmgyjgfdxvtnunneslsplwuiupfxlzbknhkwppanltcfirjcddsozoyvegurfwcsfmoxeqmrjowrghwlkobmeahkgccnaehhsveymqpxhlrnunyfdzrhbasjeuygafoubutpnimuwfjqsjxvkqdorxxvrwctdsneogvbpkxlpgdirbfcriqifpgynkrrefx",503))

    ### 超时
    # 1
    print(convert("teomqinuqnirxelpstosaodqszkogrfbxtnp",2))
    # 2
    print(convert("rmywpjscjfrhnyakdhiczbjfideaugelvekkpcmyjgfwghijqsoqtxxdacdwkjifpusgweefmmdtvlcmdqeypbdqfimq",87))

解2 2021/8/24 O(n)

def convert(s: str, numRows: int) -> str:
    '''
    从解法1看,O(n^2)不行
    这题肯定有 O(n)的解法
    '''
    # P   A   H   N
    # A P L S I I G
    # Y   I   R
    '''
    numRows=3
    x为下标,找到下标变化的规律
    row=0,x=x+4,直到s尾
    row=1,x=x+2,直到s尾
    row=2,x=x+4,直到s尾
    '''
    # p     i     n
    # a   l s   i g
    # y a   h r
    # p     i
    '''
    numRows=4
    x为下标,找到下标变化的规律
    row=0,x=x+6,直到s尾
    row=1,x=x+4 || x=x+2,取决于方向,直到s尾
    row=2,x=x+2 || x=x+4,取决于方向,直到s尾
    row=3,x=x+6,直到s尾
    
    有规律:
    numRows=n
    row=0,x=x+(n-1)*2,直到s尾
    row=1,x=x+(n-2)*2【向下】 || x=x+row*2【向上】,直到s尾
    row=2,x=x+(n-3)*2【向下】 || x=x+row*2【向上】,直到s尾
    ...
    
    通用规律:
    numRows=n
    row,x=x+(n-(row+1))*2【向下】 || x=x+row*2【向上】,直到s尾
    
    这个解法,O(n)
    '''
    len=s.__len__()
    ### 错误 - 1
    # if numRows==1 or numRows==len: return s
    if numRows==1 or numRows>=len: return s
    ### 错误 - 1
    res=s[0]
    x=0
    dir=-1
    row=0
    while row<numRows:
        new=x+((numRows-(row+1))<<1) if dir==-1 else x+(row<<1)
        dir=-dir
        if new>=len:
            row+=1
            x=row
            dir=-1
            if row<numRows: res+=s[x]
            continue
        if x != new:
            x=new
            res+=s[x]
    return res

if __name__ == '__main__':
    print(convert("PAYPALISHIRING",3))
    print(convert("PAYPALISHIRING",4))
    print(convert("A",1))

    ### 错误
    # 1
    print(convert("A",2))

解2确实是O(n)的解法,但低于80+%的解法,还有优化的空间!

当我把import numpy as np去掉之后,结果变成了,

导入一个模块,对时间影响竟然这么大!

解3 2021/8/24 O(n)

优化了首行和尾行,代码丑了一点。不过,实测,解3解2运行时间并没有多少区别,leetcode同一个答案,
有时候44ms,有时候60ms,这个时间也就大概看看吧,没大多意义。

def convert(s: str, numRows: int) -> str:
    # P   A   H   N
    # A P L S I I G
    # Y   I   R

    # p     i     n
    # a   l s   i g
    # y a   h r
    # p     i

    len=s.__len__()
    if numRows==1 or numRows>=len: return s
    res=''
    x=0
    dir=-1
    row=0
    while row<numRows:
        res+=s[x]
        if row==0:
            x = x + ((numRows - (row + 1)) << 1)
            if x>=len:
                row+=1;x=row;dir=-1
        elif row==numRows-1:
            dir=1
            x = x + (row << 1)
            if x>=len: break
        else:
            x = x + ((numRows - (row + 1)) << 1) if dir == -1 else x + (row << 1)
            dir=-dir
            if x>=len:
                row+=1;x=row;dir=-1
    return res

posted @ 2021-08-24 07:39  wwcg2235  阅读(49)  评论(0)    收藏  举报