【leetcode系列】【py3】【中等】Z 字形变换

题目:

【leetcode系列】【py3】【中等】Z 字形变换

原题链接: https://leetcode-cn.com/problems/zigzag-conversion/

 

解题思路:

抛开原始字符串,直接使用字符串编号,转换后的排列如下:

3阶:

0    4(0+4)   8(4+4)   12(8+4)   16(12+4)  
1 3(1+2) 5(3+2) 7(5+2) 9(7+2) 11(9+2) 13(11+2) 15(13+2) 17(15+2) 19(17+2)
2   6(2+4)   10(6+4)   14(10+4)   18(14+4)  

4阶:

0     6(0+6)     12(6+6)     18(12+6)
1   5(1+4) 7(5+2)   11(7+4) 13(11+2)   17(13+4) 19(17+2)
2 4(2+2)   8(4+4) 10(8+2)   14(10+4) 16(14+2)   20(16+4)
3     9(3+6)     15(9+6)     21(15+6)

 

3阶的可能不太明显,4阶比较明显,用4阶的为例

每行的下标间隔总数为6(2 * (4 - 1)),将每行的间隔分为左间隔和右间隔,变化如下:

左间隔 右间隔
6 0
4 2
2 4
0 6

每往下一行,左间隔-2,右间隔+2

每行的第一个字符的编号就是行号,然后根据行号,进行左右间隔轮换跳转获取字符

每个字符只循环了一次,时间复杂度为O(n)

 

代码实现:

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if 0 == len(s):
            return s
        
        total = max(2 * (numRows - 1), 1)

        # 使用list的原因,是因为''.join()的效率,比str的+效率要高
        res_str = []
        
        cycle_num = 0
        for row in range(0, numRows):
            index = row
            if index >= len(s): break
            res_str.append(s[index])
            left = total - 2 * row
            right = 2 * row
            while index < len(s):
                cycle_num += 1
                if 0 != left:
                    index += left
                    if index < len(s): res_str.append(s[index])

                if 0 != right:
                    index += right
                    if index < len(s): res_str.append(s[index])
                    
        return ''.join(res_str)