作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级
在力扣(LeetCode)的题库中,"Z 字形变换"是一个独特的字符串处理问题,它考验着对字符串操作的精确控制和对问题模型的理解。本文将深入探讨这个问题,并提供一个高效的解决方案。
问题描述
给定一个字符串和一个行数,要求你按照从上往下、从左到右的顺序,进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING"
,行数为 3 时,排列如下:
P A H N A P L S I I G Y I R
之后,你的输出需要按行读取,输出一个新的字符串,即 "PAHNAPLSIIGYIR"
。
解题思路
观察 Z 字形排列,我们可以发现,除了第一行和最后一行外,其他每一行中间都会夹杂一个来自斜线上的字符。每一“轮”Z字形的字符数是固定的,为 2 * numRows - 2
(除去首尾两行后,上下两部分各占据 numRows - 1
,加上首尾两行即得公式)。
基于这个观察,我们可以通过计算每个字符在 Z 字形排列中的位置,从而构建出最终的字符串。
解题步骤
- 创建一个数组,长度等于给定的行数,用于存储每行的字符。
- 遍历给定字符串的每个字符,计算出该字符应该放置在哪一行。
- 按照从上到下、从左到右的顺序,将字符添加到对应行的字符串中。
- 最后,将这些行连接起来,形成最终的字符串。
代码示例
初步尝试:直接模拟
最初可能会尝试直接按照 Z 字形排列的逻辑去模拟整个过程,例如,尝试为每一行和斜线创建单独的存储空间,然后尝试填充它们。
def convert_v1(s: str, numRows: int) -> str: # 特殊情况处理 if numRows == 1 or numRows >= len(s): return s # 初始化存储结构 z_matrix = [[] for _ in range(numRows)] row, down = 0, True for c in s: z_matrix[row].append(c) if row == numRows - 1: down = False elif row == 0: down = True row += 1 if down else -1 # 结果拼接 result = '' for r in z_matrix: result += ''.join(r) return result
问题:这个方法试图通过控制方向变量 down
来模拟“Z”字形的折返运动,但实际上它忽略了在 numRows 为 1 或者输入字符串很短时的特殊情况,容易造成索引错误或者不必要的复杂度。
改进:合并斜线到行
认识到斜线上的字符其实可以直接并入对应的行中,不需要单独处理斜线部分,这样可以简化代码和逻辑。
def convert_v2(s: str, numRows: int) -> str: if numRows == 1 or numRows >= len(s): return s rows = [''] * numRows current_row, step = 0, -1 for char in s: rows[current_row] += char if current_row == 0 or current_row == numRows - 1: step = -step current_row += step return ''.join(rows)
这个版本已经比较接近最终的解法了,但仍然可以在细节上进行优化和规范,例如增加注释来提高代码的可读性。
最终版本:增加注释和细节优化
在最终版本中,我们添加了必要的注释,并确保代码清晰、简洁、易于理解。
def convert(s: str, numRows: int) -> str: # 处理特殊情况,提高效率 if numRows == 1 or numRows >= len(s): return s # 初始化存储每行字符串的列表 rows = [''] * numRows # 初始化当前行和行进方向 current_row, step = 0, -1 for char in s: rows[current_row] += char # 到达Z字形的顶部或底部时,改变方向 if current_row == 0 or current_row == numRows - 1: step = -step current_row += step # 将所有行的字符串连接并返回 return ''.join(rows) # 示例测试代码 s = "PAYPALISHIRING" numRows = 3 print(convert(s, numRows)) # 输出: "PAHNAPLSIIGYIR"
代码解释
- 初始化一个列表
rows
,长度为numRows
,用于存储每一行的字符串。 - 使用
current_row
来追踪当前字符应该放在哪一行。step
用于控制行号的增减,实现“Z”字形的折返运动。 - 遍历字符串中的每个字符,根据当前行号添加到相应的行字符串中。当当前行号为第一行或最后一行时,改变行号的增减方向。
- 最后,使用
''.join(rows)
将所有行的字符串连接成一个字符串。
结语
"Z 字形变换"问题通过模拟字符串的重新排列过程,不仅测试了对字符串处理的能力,也考察了对问题的逻辑分析和转换能力。如果本文对你有帮助,点赞是对作者最大的鼓励哦!
欢迎关注微信公众号 数据分析螺丝钉