6. Z 字形变换(Python)

6. Z 字形变换

题目:
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:

在这里插入图片描述

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

解法一:
以s = ‘leetcod’ , numRows = 3为例
res[0] = l c
res[1] = e t o
res[2] = e d

class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows < 2 or numRows >= len(s):   # 行数小于2不会形成z字形,行数大于字符串长度字符串只能成纵向排列且只有一列
            return s 
        res = ["" for i in range(numRows)]   # 列表生成器,生成与行数个数对应的空字符串
        i,flag = 0,-1     # 初始化i,flag
        for c in s:  # 遍历整个字符串
            res[i] += c    # 将遍历到的字符存入生成的空字符串中
            if i == 0 or i == numRows-1:     # 判定是否已经到行头与行尾,如果是则反转,倒序往相应的字符串中添加字符
                flag = - flag

            i += flag
        
        return "".join(res)   # 字符串合成,并返回

解法二:

def convert(s,numRows):
    # cache 生成行数的列表例如以numRows = 3为例:
    # 然后整合成列表cache = [0,1,2,1]
    """
    0       0
    1   1   1
    2
    """
    cache = [i for i in range(numRows)] + [i for i in range(1,numRows - 1)][::-1]
    # 按行对应字符串,并分别将每行的字符串保存到列表中
    res = ['' for _ in range(numRows)]
    for i ,c in enumerate(s):
    	# i%len的数对应cache中元素的下标,而cache中的元素又对应行数
        res[cache[i%len(cache)]] += c
		
    return ''.join(res)
### Z字形变换算法实现与解释 #### 算法概述 Z字形变换是一种特殊的字符串排列方式,其核心在于按照特定的行数 `numRows` 将字符串重新排列成一种类似于“Z”形状的形式。最终目标是从这种排列中按照行优先的方式读取出新的字符串。 对于输入字符串 `s` 和行数 `numRows` 的约束条件为: - $1 \leq |s| \leq 1000$ - $1 \leq numRows \leq 1000$ 当 `numRows = 1` 或者字符串长度小于等于 `numRows` 时,可以直接返回原字符串[^3]。 --- #### 算法逻辑 该问题可以通过模拟字符分配的过程来解决。具体步骤如下: 1. **初始化存储结构** 创建一个列表(数组),其中每个元素代表一行的内容。初始为空字符串。 2. **遍历字符串并分配字符** 使用一个变量记录当前字符应放置在哪一行,并通过方向标志控制上下移动的趋势。如果到达顶部或底部,则改变方向。 3. **拼接结果** 遍历完成后,将每一行的结果依次连接起来形成最终字符串。 这种方法的时间复杂度为 $O(n)$,空间复杂度也为 $O(n)$,因为需要额外的空间存储每行的数据[^4]。 --- #### Python 实现代码 以下是基于上述逻辑的 Python 实现代码: ```python def convert(s: str, numRows: int) -> str: if numRows == 1 or len(s) <= numRows: # 特殊情况处理 return s rows = [''] * numRows # 初始化每行为空字符串 current_row = 0 # 当前行索引 going_down = False # 方向标志,默认向下 for char in s: rows[current_row] += char # 将字符加入对应行 # 判断是否达到边界并调整方向 if current_row == 0 or current_row == numRows - 1: going_down = not going_down # 更新当前行号 current_row += 1 if going_down else -1 return ''.join(rows) # 合并所有行得到结果 ``` --- #### 示例解析 假设输入字符串为 `"LEETCODEISHIRING"`,行数为 `3`,则执行过程如下: 1. 初始化三行数据:`['', '', '']` 2. 开始遍历字符串并将字符逐一放入对应的行中: - `'L'` 放入第 0 行 → `[L, , ]` - `'E'` 放入第 1 行 → `[L, E, ]` - `'E'` 放入第 2 行 → `[L, E, E]` - `'T'` 变换方向放回第 1 行 → `[L, ET, E]` ... 3. 最终各行列状态为: ``` Row 0: LCIRE Row 1: TOESII Row 2: GEDHN ``` 4. 拼接结果为 `"LCIRETOESIIGEDHN"` --- #### 边界情况讨论 1. 如果 `numRows = 1`,无需任何操作直接返回原始字符串。 2. 如果字符串长度小于等于 `numRows`,同样不需要特殊处理,只需简单分隔即可[^5]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值