LeetCode【0006】Z字形变换

server/2024/11/14 0:39:48/

本文目录

  • 1 中文题目
  • 2 求解思路
  • 3 题目总结

1 中文题目

将一个给定字符串 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 . l e n g t h ≤ 1000 1 \leq s.length \leq 1000 1s.length1000
  • s 由英文字母(小写和大写)、‘,’ 和 ‘.’ 组成
  • 1 ≤ n u m R o w s ≤ 1000 1 \leq numRows \leq 1000 1numRows1000

2 求解思路

2.1 基础解法:模拟法

思路
使用多个数组模拟Z字形走位,按照向下和向上两个方向交替移动,在首行和末行时改变移动方向。 模拟的规则:从上到下填充字符时,行号增加;从下到上填充字符时,行号减少;在第一行时向下移动;在最后一行时向上移动。

步骤1: 初始化

  • 创建numRows个空数组,每个数组对应一行
  • 初始化当前行号和移动方向

步骤2: 遍历字符

  • 将每个字符放入对应行的数组中
  • 根据当前位置更新移动方向
  • 更新当前行号

步骤3: 合并结果

  • 将所有行的字符合并成最终字符串

Python代码

python">class Solution:def convert(self, s: str, numRows: int) -> str:"""Z字形变换的模拟法实现Args:s: 输入字符串numRows: 指定的行数Returns:按Z字形变换后的字符串示例:输入: s = "PAYPALISHIRING", numRows = 3过程: P   A   H   NA P L S I I GY   I   R输出: "PAHNAPLSIIGYIR""""# 特殊情况处理:当行数为1或字符串长度小于行数时if numRows == 1 or numRows >= len(s):return s# 初始化numRows个空字符串数组,用于存储每行的字符rows = [[] for _ in range(numRows)]# 当前行号(表示当前字符应该放在第几行)curr_row = 0# 移动方向(1表示向下,-1表示向上)step = 1# 遍历字符串中的每个字符for char in s:# 将当前字符添加到对应行rows[curr_row].append(char)# 在首行或末行时需要改变移动方向if curr_row == 0:  # 当前在第一行step = 1  # 改为向下移动elif curr_row == numRows - 1:  # 当前在最后一行step = -1  # 改为向上移动# 更新当前行号curr_row += step# 合并所有行的字符形成最终结果# 先将每一行的字符数组合并成字符串,再将所有行的字符串连接return ''.join(''.join(row) for row in rows)

时空复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)
    • 遍历字符串一次: O ( n ) O(n) O(n),其中 n n n字符串长度
    • 合并结果时再次遍历: O ( n ) O(n) O(n)

总体时间复杂度: O ( n ) O(n) O(n)

  • 空间复杂度: O ( n ) O(n) O(n)
    • r o w s rows rows数组: O ( n u m R o w s ) O(numRows) O(numRows)个数组。虽然使用了 n u m R o w s numRows numRows个数组,但所有数组中存储的字符总数仍然是 n n n
    • 其他变量: O ( 1 ) O(1) O(1)

总体空间复杂度: O ( n ) O(n) O(n)


2.2 优化解法:数学规律

思路
在这里插入图片描述
蓝框中表示一个周期,蓝框中的字符数即为周期长度。

周期长度 = 2 * numRows - 2

  • 向下移动需要 numRows
  • 向上移动需要 numRows - 2 步(不包括首尾行)
  • 总步数 cycle= numRows + (numRows - 2) = 2 * numRows - 2

位置的规律:

  • 首行(i=0)和末行(i=numRows-1):
    • 字符位置:k * cycle ,其中k为周期序号(0, 1, 2, …)
  • 中间行:(中间的行,每一行一个周期内只有2个字符)
    • 第一个字符位置:k * cycle + i
    • 第二个字符位置:k * cycle + (cycle - i)
  • 末行(i=numRows-1):
    • 字符位置:k * cycle + i,其中k为周期序号(0, 1, 2, …)

示例:

对于 numRows = 4 的情况,设周期序号为k:

python">第0(i=0)- 字符位置:6k     (k=0,1,2,...)
- 实际位置:0, 6, 12, ...1(i=1)- 第一个字符位置:6k + 1   (k=0,1,2,...)
- 第二个字符位置:6k + 5   (k=0,1,2,...)
- 实际位置:1, 5, 7, 11, 13, ...2(i=2)- 第一个字符位置:6k + 2   (k=0,1,2,...)
- 第二个字符位置:6k + 4   (k=0,1,2,...)
- 实际位置:2, 4, 8, 10, 14, ...3(i=3)- 字符位置:6k + 3     (k=0,1,2,...)
- 实际位置:3, 9, 15, ...

python代码

python">class Solution:def convert(self, s: str, numRows: int) -> str:"""使用数学方法实现Z字形变换核心思想:1. 找出Z字形排列的周期规律2. 通过数学公式直接计算每个字符在结果中的位置参数说明:s: 输入字符串numRows: Z字形的行数示例分析:对于 numRows = 4 的情况:周期 = 2 * numRows - 2 = 6P     I    NA   L S  I GY A   H RP     I规律分析:第0行: 0,     6,     12    -> 间隔6 (周期)第1行: 1,   5,7,   11,13   -> 间隔4,2,4,2第2行: 2, 4, 8,10, 14      -> 间隔2,4,2,4第3行: 3,     9,     15    -> 间隔6 (周期)"""# 特殊情况处理if numRows == 1 or numRows >= len(s):return s# 计算周期长度cycle = 2 * numRows - 2# 存储结果result = []# 遍历每一行for i in range(numRows):# 遍历每个周期的起始位置for j in range(0, len(s), cycle):# 添加当前周期的第一个字符(如果存在)if j + i < len(s):result.append(s[j + i])# 对于中间行(非首尾行),添加当前周期的第二个字符(如果存在)if i != 0 and i != numRows - 1:  # 不是首行也不是末行# 计算当前周期中第二个字符的位置second_pos = j + cycle - iif second_pos < len(s):result.append(s[second_pos])# 合并所有字符return ''.join(result)

时空复杂度分析

  • 时间复杂度
    • 外层循环:遍历每一行O(numRows)
    • 内层循环:每行处理约 n/cycle个字符

总的字符处理数量仍然是 n,因此总时间复杂度为 O(n)

  • 空间复杂度
    • 结果数组:存储所有字符,O(n)
    • 其他变量:O(1)

总空间复杂度:O(n)


2.3 最优解法:字符串拼接法

思路
把Z字形看作是在若干行之间来回移动的过程,记录每一行的字符,最后拼接起来。具体实现步骤

  • 初始化
    • 创建numRows个空字符串,每个字符串对应一行
    • 设置当前行号curRow = 0
    • 设置移动方向step = 1(1表示向下,-1表示向上)
  • 遍历原字符串
    • 把当前字符添加到当前行对应的字符串
    • 根据当前位置更新移动方向:
      • 到达第一行(curRow = 0)时,向下移动(step = 1)
      • 到达最后一行(curRow = numRows-1)时,向上移动(step = -1)
    • 更新当前行号:curRow += step
  • 合并结果
    • 将所有行的字符串按从上到下的顺序拼接起来

示例
字符串 “PAYPALISHIRING” 和 numRows = 4 为例:

python">初始状态:
row[0] = ""
row[1] = ""
row[2] = ""
row[3] = ""逐字符处理:
P: 放入第0行,向下移动
row[0] = "P"
row[1] = ""
row[2] = ""
row[3] = ""A: 放入第1行,继续向下
row[0] = "P"
row[1] = "A"
row[2] = ""
row[3] = ""Y: 放入第2行,继续向下
row[0] = "P"
row[1] = "A"
row[2] = "Y"
row[3] = ""P: 放入第3行,改为向上移动
row[0] = "P"
row[1] = "A"
row[2] = "Y"
row[3] = "P"A: 放入第2行,继续向上
row[0] = "P"
row[1] = "A"
row[2] = "YA"
row[3] = "P"...以此类推

python代码

python">class Solution:def convert(self, s: str, numRows: int) -> str:"""使用字符串拼接法实现Z字形变换核心思想:1. 创建numRows个字符串,分别对应每一行2. 遍历原字符串,将每个字符追加到对应行的字符串中3. 设置方向标志,在到达边界时改变方向4. 最后将所有行的字符串拼接起来参数说明:s: 输入字符串numRows: Z字形的行数返回值:返回Z字形变换后的字符串"""# 特殊情况处理if numRows == 1 or numRows >= len(s):return s# 初始化每一行的字符串rows = [''] * numRows# 当前行号cur_row = 0# 移动方向,1表示向下,-1表示向上step = 1# 遍历每个字符for c in s:# 将当前字符添加到对应行rows[cur_row] += c# 在首行时向下移动if cur_row == 0:step = 1# 在末行时向上移动elif cur_row == numRows - 1:step = -1# 更新当前行号cur_row += step# 合并所有行的字符串return ''.join(rows)

时空复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
    • rows数组:存储n个字符,O(n)
    • 其他变量:O(1)

3 题目总结

题目难度:中等
数据结构: 字符串
应用算法数学规律


http://www.ppmy.cn/server/141716.html

相关文章

golang分布式缓存项目 Day6 防止缓存击穿

该项目原作者&#xff1a;https://github.com/geektutu/7days-golang。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习。 1 缓存雪崩、缓存击穿与缓存穿透 概念解析&#xff1a; 缓存雪崩&#xff1a;缓存在同一时刻全部失效&#xff0c;造成瞬…

MySQL日期时间函数大全

DAYOFWEEK(date)  返回日期date是星期几(1星期天,2星期一,……7星期六,ODBC标准) mysql> select DAYOFWEEK(1998-02-03);   -> 3 WEEKDAY(date)  返回日期date是星期几(0星期一,1星期二,……6 星期天)。 mysql> select WEEKDAY(1997-10-04 22:23:00);   -> 5…

【VBA实战】用Excel制作排序算法动画续

为什么会产生用excel来制作排序算法动画的念头&#xff0c;参见【VBA实战】用Excel制作排序算法动画一文。这篇文章贴出我所制作的所有排序算法动画效果和源码&#xff0c;供大家参考。 冒泡排序&#xff1a; 插入排序&#xff1a; 选择排序&#xff1a; 快速排序&#xff1a;…

【网络工程】计算机硬件概述

1. 计算机硬件概述 1.1 定义与组成 计算机硬件是指组成计算机系统的物理设备&#xff0c;包括但不限于中央处理器&#xff08;CPU&#xff09;、存储器、输入设备、输出设备等。这些设备共同构成了计算机的物理基础&#xff0c;使得计算机能够执行各种计算任务。 CPU&#x…

汽车牌照识别系统的设计与仿真(论文+源码)

1设计原理 车牌识别系统的设计是一项利用车辆的动态视频或者静态图像实现牌照区域定位车牌号码识别的技术。其硬件部分通常包括触发设备、拍摄设备、照明设备、图像收集设备、进行车牌号码识别的处理器等&#xff0c;其软件的关键部分包含车牌区域定位的算法、车牌字符的分割算…

Spring框架之适配器模式 (Adapter Pattern)

适配器模式&#xff08;Adapter Pattern&#xff09;详解 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它的主要作用是将一个类的接口转换成客户端期望的另一个接口&#xff0c;使原本由于接口不兼容而无法一起工作的类可以协同工作。…

《MYSQL45讲》误删数据怎么办

对误删数据分类的话&#xff0c;有 1.delete 误删行 2.drop table 或者truncate table 语句误删表 3.使用drop database 误删数据库 4.使用rm命令误删整个MYSQL实例 一&#xff0c;误删行 一下操作前置条件是&#xff1a;binlog的格式是row&#xff0c;并且binglog_row_im…

SpringBoot(三)

最佳实践 1.SpringBoot 应用如何编写 引入场景依赖 官方文档 查看自动配置了哪些&#xff08;选做&#xff09; 自己分析&#xff0c;引入场景对应的自动配置一般都生效了配置文件中 debugtrue 开启自动配置报告。 Negative&#xff08;不生效&#xff09;Positive&#xff0…