【LeetCode】修炼之路-0006-Zigzag Conversion (Z 字形变换)【python】

news2024/11/26 11:01:27

题目

The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P A H N
A P L S I I G
Y I R
And then read line by line: “PAHNAPLSIIGYIR”

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input: s = “PAYPALISHIRING”, numRows = 3
Output: “PAHNAPLSIIGYIR”

Example 2:

Input: s = “PAYPALISHIRING”, numRows = 4
Output: “PINALSIGYAHRPI”
Explanation:
P I N
A L S I G
Y A H R
P I

Example 3:

Input: s = “A”, numRows = 1
Output: “A”

Constraints:

1 <= s.length <= 1000
s consists of English letters (lower-case and upper-case), ‘,’ and ‘.’.
1 <= numRows <= 1000

Topics
Companies
The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

题目分析

我们一开始刷算法题的时候,会遇到读不懂题目的问题。别灰心,慢慢来。
这个Z字形变换,看似花里胡哨,又是竖着又是斜着,交替变化。
但是我们抓住主要矛盾,看一下输入和输出。
实际上是根据给定的行数,分成几列展示。

所以比如对于ABCDEFGHI这样的字符串,要求分成3行,我们可以把问题退化成2个问题,
1.先实现简单的列式排列

实现分3行显示,每列都是从上到下
A D G
B E H
C F I

2.再增加方向变化的逻辑

设置一个开关一样的变量,控制从上往下还是从下往上
A E I
B D F H
C G

初等代码

伪代码

  1. 初始化用于输出的字符串
  2. 循环字符串
  3. 增加方向变化的逻辑

1. 初始化用于输出的字符串

分成n行,那么我们肯定要有3个字符串的变量来存

基本操作-使用for循环初始化

# 方法1:使用循环初始化
rows = []
for i in range(numRows):
    rows.append('')

进阶操作1-列表生成式

# 方法2:列表生成式
rows = ['' for _ in range(numRows)]

进阶操作2-序列乘法

# 方法3:序列乘法
# 语法:sequence * n
rows = [''] * numRows

2. 循环字符串

def convert_simple(s: str, numRows: int) -> str:
    # 初始化行
    rows = [''] * numRows
    
    # 按列填充字符
    for i, char in enumerate(s):
        row_idx = i % numRows  # 循环获取行索引
        rows[row_idx] += char # 这里的行索引,实际上就是rows的下标
    
    # 合并所有行
    return '\n'.join(rows)

# 测试
s = "ABCDEFGHI"
result = convert_simple(s, 3)
print(result)

![(https://i-blog.csdnimg.cn/direct/7577361dc8c448129716072ea5581098.png)

3. 增加方向变化的逻辑

一开始,step是1,因为是从上往下,在rows列表里也就是从左往右,从小到大递增索引值的。然后到了第三个值curr_row==2, rows的下标就要往左走了,这个时候,置step为-1。我们列表分析如下

字符i % 3
(看似能用
但实际无关)
curr_row
(改变前)
是否改变方向stepcurr_row
(改变后)
rows
A00在顶部,向下11[‘A’,‘’,‘’]
B11继续向下12[‘A’,‘B’,‘’]
C22在底部,向上-11[‘A’,‘B’,‘C’]
D01继续向上-10[‘A’,‘BD’,‘C’]
E10在顶部,向下11[‘AE’,‘BD’,‘C’]
F21继续向下12[‘AE’,‘BDF’,‘C’]
G02在底部,向上-11[‘AE’,‘BDF’,‘CG’]
H11继续向上-10[‘AE’,‘BDFH’,‘CG’]
I20在顶部,向下11[‘AEI’,‘BDFH’,‘CG’]

通过这个表格可以清楚地看到:

  1. i % 3的值与实际的行为完全不对应
  • 比如D和E,i % 3都是0,但一个在第1行继续向上,一个在第0行开始向下
  • 实际的方向变化完全取决于curr_row的位置
  1. 真正起决定作用的是curr_row:
  • 在0时向下
  • 在2(底部)时向上
  • 其他情况保持原方向

代码如下:

class Solution:
    def convert(self, s: str, numRows: int) -> str:
            
        rows = [''] * numRows
        step = 1
        curr_row = 0
        
        for char in s:
            rows[curr_row] += char
            
            # 如果到达底部,改变方向向上
            if curr_row == numRows - 1:
                step = -1
            # 如果到达顶部,改变方向向下
            elif curr_row == 0:
                step = 1
                
            curr_row += step
        
        return ''.join(rows)

非常优雅!点击运行也是可以的,
在这里插入图片描述

我们勇敢提交!阿勒?说好的accepted呢!
在这里插入图片描述
我们可以看到报错出现在行数为1的时候
让我们分析一下当 numRows = 1 时的执行过程:

字符numRowscurr_row
(改变前)
stepcurr_row
(改变后)
问题说明
A1011curr_row从0变成1
B11-10curr_row=1已经越界!

问题在于:

  1. 当 numRows = 1 时,只有一行(下标为0)

  2. 但我们的代码中:

    • 初始 curr_row = 0
    • 当 curr_row == 0 时,执行 step = 1
    • curr_row += step 导致 curr_row 变成 1
    • 此时 curr_row = 1 已经超出了 rows 的范围(因为rows只有一个元素)

好了,我们现在知道了问题,可是,为什么会出现这样的问题呢,为什么没有这样的直觉呢。哎,这就是编程经验的问题了,来看看我们这里的代码。
在这里插入图片描述
我们通过if-elif,希望代码进入不同的逻辑,但是因为有numRows变量的参与,使得我们被迷惑了,这里如果两个条件相等,就会让程序进入不可控的状态。所以对于numRows==1的情况,我们需要额外声明:

if numRows == 1:
	return s

好了,我们打上补丁,重新运行一下:

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows == 1:
            return s
            
        rows = [''] * numRows
        step = 1
        curr_row = 0
        
        for char in s:
            rows[curr_row] += char
            
            # 如果到达底部,改变方向向上
            if curr_row == numRows - 1:
                step = -1
            # 如果到达顶部,改变方向向下
            elif curr_row == 0:
                step = 1
                
            curr_row += step
        
        return ''.join(rows)

在这里插入图片描述
怎么memory那么低,一定是我打开的方式不对,再运行一次!
在这里插入图片描述
可以

知识点总结

列表生成式

列表生成式属于可以体现the zen of python的特性之一,理解好列表生成式,用好列表生成式,可以让你的代码更清晰,建议多看,多练习,掌握列表生成式的使用方法,可以让你的代码更紧凑,可读性更好,代码更优雅。

1. 基本语法

# 1.1 最基础形式
[x for x in range(5)]  # [0, 1, 2, 3, 4]

# 1.2 带条件过滤
[x for x in range(10) if x % 2 == 0]  # [0, 2, 4, 6, 8]

# 1.3 带转换操作
[str(x) for x in range(5)]  # ['0', '1', '2', '3', '4']

# 1.4 多重循环
[(x, y) for x in range(2) for y in range(2)]  # [(0,0), (0,1), (1,0), (1,1)]

2. 实用技巧

2.1 处理字符串
# 提取所有元音字母
text = "hello world"
vowels = [c for c in text if c in 'aeiou']  # ['e', 'o', 'o']

# 大写转换
[c.upper() for c in "hello"]  # ['H', 'E', 'L', 'L', 'O']

# 去除空格
words = "  python   is  awesome  "
clean = [w for w in words.split() if w]  # ['python', 'is', 'awesome']
2.2 数学运算
# 平方数
squares = [x**2 for x in range(10)]  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 欧几里得距离
points = [(1,1), (2,3), (3,5)]
distances = [((x**2 + y**2)**0.5) for x,y in points]

# 矩阵转置
matrix = [[1,2,3], [4,5,6]]
transposed = [[row[i] for row in matrix] for i in range(3)]
2.3 数据处理
# 字典处理
prices = {'apple': 0.5, 'banana': 0.25, 'orange': 0.75}
expensive = [(fruit, price) for fruit, price in prices.items() if price > 0.5]

# 数据清洗
data = [1, None, 3, '', False, 5]
cleaned = [x for x in data if x is not None and x != '']

# 扁平化列表
nested = [[1,2,3], [4,5,6], [7,8,9]]
flat = [num for sublist in nested for num in sublist]

3. 高级应用

3.1 条件表达式

# if-else在列表生成式中
[x if x > 0 else 0 for x in [-2, -1, 0, 1, 2]]  # [0, 0, 0, 1, 2]

# 多条件
[
    'high' if x > 7 
    else 'medium' if x > 3 
    else 'low' 
    for x in range(10)
]

3.2 集合和字典生成式

# 集合生成式
{x**2 for x in range(5)}  # {0, 1, 4, 9, 16}

# 字典生成式
{x: x**2 for x in range(5)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

3.3 生成器表达式

# 使用()创建生成器表达式(节省内存)
squares = (x**2 for x in range(1000000))

序列乘法

序列乘法,在初始化的时候,比for循环效率好很多,建议初始化的时候,考虑用序列化乘法来进行一些初始化

# 字符串乘法
'a' * 3          # 'aaa'
'hello ' * 2     # 'hello hello '

# 列表乘法
[1] * 3          # [1, 1, 1]
['hi'] * 2       # ['hi', 'hi']

# 元组乘法
(1,) * 3         # (1, 1, 1)
('a', 'b') * 2   # ('a', 'b', 'a', 'b')

# 例如:创建交替模式
alternating = [0, 1] * 5    # [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

编程经验0006

  1. 写if-elif时要检查条件是否可能相等
  2. 特别是涉及变量计算的条件判断时(如 numRows-1)
  3. 要考虑边界情况下这些条件的值是否会产生冲突

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

荣耀电脑管家-系统重装之查询设备序列号

winr输入cmd&#xff0c;再命令行中输入 wmic bios get serialnumber 如下所示

代码随想录算法训练营第六天|454四数相加II、 383赎金信、15三数之和、18四数之和

day06 1. 454四数相加II 首先定义 一个unordered_map&#xff0c;key放a和b两数之和&#xff0c;value 放a和b两数之和出现的次数。遍历大A和大B数组&#xff0c;统计两个数组元素之和&#xff0c;和出现的次数&#xff0c;放到map中。定义int变量count&#xff0c;用来统计 …

YAML格式校验API:免费工具的使用指南

YAML&#xff08;YAML Ain’t Markup Language&#xff09;是一种人类可读的数据序列化格式&#xff0c;广泛用于配置文件、数据交换等场景。由于其简洁的语法和良好的可读性&#xff0c;YAML 在开发和运维领域中越来越受到欢迎。然而&#xff0c;在使用 YAML 时&#xff0c;格…

Xcode文件默认存储位置-使用c++file保存文件默认路径以及设置为路径为当前项目路径

Xcode文件默认存储位置-使用cfile保存文件默认路径以及设置为路径为当前项目路径 1.概述 使用Xcode工具开发时候&#xff0c;遇到C调用file创建文件后&#xff0c;在当前项目中找不到文件路径。这是由于xcode会将文件保存到默认设置的路径。下面是查看文件默认存储路径和修改…

数组中的算法

目录 1.什么是数组 2.数组上的算法 2.1二分查找算法 什么是二分查找算法&#xff1f; 算法步骤 算法时间复杂度 一个问题 例题 题目分析 解题代码 2.2双指针法 什么是双指针法&#xff1f; 例题 题目分析 解题代码 1.什么是数组 数组是在一块连续的内存空间…

C++,STL 047(24.10.24)

内容 对set容器的元素进行查找与统计。 运行代码 #include <iostream> #include <set>using namespace std;void printSet(set<int> &s) {for (set<int>::iterator it s.begin(); it ! s.end(); it){cout << *it << " ";…

linux-牛刀小试

题目一&#xff1a; 1.第一问 首先创建用户tab在超级用户root的终端输入useradd tab 切换到tab用户&#xff1a; 推出重新登录到tab用户或者su – tab切换到tab用户 2.第二问 在桌面创建SHEGNCHAN目录 在SHENGCHAN文件夹下创建相应的文件&#xff1a; 3.第三问 首先&#…

哈希表【闭散列/开散列】

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;C/C 目录 一、unordered系列关联式容器 &#x1f31f;unordered_map ⭐unordered_map接口说明 二、底层结构 &#x1f31f;哈希概念 &#x1f31f;哈希冲突 &#x1f31f;哈希函数 &#x1f3…

基于Leaflet和SpringBoot的全球国家综合检索WebGIS可视化

目录 前言 一、Java后台程序设计 1、业务层设计 2、控制层设计 二、WebGIS可视化实现 1、侧边栏展示 2、空间边界信息展示 三、标注成果展示 1、面积最大的国家 2、国土面积最小的国家 3、海拔最低的国家 4、最大的群岛国家 四、总结 前言 在前面的博文中&#xff…

【随手笔记】远程升级之如何平衡下载包大小与速率?

1. 远程升级基本信息 使用NB_BC26模组&#xff0c;通过AT指令使用TCP的协议与公司后台交互升级的固件为BIN文件&#xff0c;使用原始固件包升级&#xff0c;未使用差分方式原始固件包有110K,大小左右&#xff0c;固件的存储为外置的FLASH W25Q16,w25q16最小存储单位为页&#…

AListFlutter(手机alist)——一键安装,可在手机/电视上运行并挂载各个网盘

前面提到软路由系统OpenWRT的时候&#xff0c;当时说过可以在OpenWRT里安装alist&#xff0c;然后挂载网盘&#xff0c;这样就可以通过webdav的方式在家庭局域网下的任何设备都可以访问操作这些网盘&#xff0c;摆脱硬盘空间不够的问题。 但alist的官方版本是没有手机版本的&a…

【Java】探秘正则表达式:深度解析与精妙运用

目录 引言 一、基本概念 1.1 元字符 1.2 预定义字符类 1.3 边界匹配符 1.4 数量标识符 1.5 捕获与非捕获分组 二、Java中的正则表达式支持 三、正则表达式的使用示例 3.1 匹配字符串 3.2 替换字符串 3.3 分割字符串 3.4 使用Pattern和Matcher 3.5 捕获组和后向…

我了个超绝MATLAB——基础

由于要参加美赛&#xff0c;不想拖对队友们的后腿&#xff0c;于是一怒之下……怒了一下 创建MATLAB脚本 创建脚本 在主页——新建——脚本 中新建脚本&#xff08;Ctrln&#xff09; 保存 编辑器——保存&#xff08;Ctrls&#xff09; 运行 编辑器——运行&#xff08;F5&…

iOS--利用UITableViewDataSourcePrefetching实现平滑如丝的无限滚动

前言&#xff1a; 相信大家在网络不好的时候使用列表分页的App会获得非常不好的体验&#xff0c;由于网络的问题&#xff0c;会有明显的卡顿&#xff0c;就像抖音等App&#xff0c;那么我们是否能使用一些手段来优化这个体验呢&#xff1f;这里可以用到UITableView中另一个协议…

【案例演示】图像描述大模型示例及概念解释

【案例演示】图像描述大模型示例及概念解释 一、案例演示模型描述期望模型使用方式以及适用范围模型功能演示 二、大模型开源平台概览模型库的定义大模型开源平台 一、案例演示 模型链接&#xff1a;https://modelscope.cn/models/iic/mplug_image-captioning_coco_base_zh 模…

使用 CDN 后 Apache 的日志记录客户真实 IP

经常搭建网站服务器的都知道&#xff0c;在给站点使用了 CDN 后 Web 应用的日志记录里就会只记录 CDN 节点 IP 了&#xff0c;这就没法看到真实客户请求 IP&#xff0c;对于日志分析、运维日常维护来说就有点儿麻烦了&#xff0c;今天明月结合在五洛云服务器上搭建的Apache环境…

短视频账号矩阵系统源码---独立saas技术部署

#短视频账号矩阵系统# #短视频矩阵源码# #短视频账号矩阵系统技术开发# 抖音seo账号矩阵系统&#xff0c;短视频矩阵系统源码&#xff0c; 短视频矩阵是一种常见的视频编码标准&#xff0c;通过多账号一键授权管理的方式&#xff0c;为运营人员打造功能强大及全面的“矩阵式“…

liunx线程互斥

临界资源和临界区 临界资源&#xff1a;多线程执行流共享的资源就叫临界资源。 临界区&#xff1a;每个线程中&#xff0c;访问临界区的代码&#xff0c;就叫临界区。 互斥&#xff1a;任何时候&#xff0c;互斥保证只有一个执行流进入临界区&#xff0c;访问临界资源&#…

华为eNSP:端口安全

一、什么是端口安全 端口安全是指保护计算机端口免受未经授权的访问、攻击或滥用的一种措施。计算机上的每个服务或应用程序都依靠特定的端口进行通信。端口安全的目的是限制对计算机端口的访问&#xff0c;确保只有经过授权的用户或服务可以使用这些端口。通过配置防火墙、访…

C/C++(六)多态

本文将介绍C的另一个基于继承的重要且复杂的机制&#xff0c;多态。 一、多态的概念 多态&#xff0c;就是多种形态&#xff0c;通俗来说就是不同的对象去完成某个行为&#xff0c;会产生不同的状态。 多态严格意义上分为静态多态与动态多态&#xff0c;我们平常说的多态一般…