LeetCode50天刷题计划(Day 5—— Z 字形变换 10.50-13:00)

本文介绍了LeetCode中的Z字形变换问题,即如何将字符串按照Z字形排列并转换。文章提供了两种解决方案,一种使用二维数组模拟,另一种采用一维数组模拟,同时附带了详细的Python和C++代码实现。文章强调了处理边界条件和字符串不可变性的关键点。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

加油捏~

一、题目

Z 字形变换

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

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

P   A   H   N
A P L S I I G
Y   I   R

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

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例

示例 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.length <= 1000
s 由英文字母(小写和大写)、‘,’ 和 ‘.’ 组成
1 <= numRows <= 1000

二、思路

1.垃圾

鼠鼠啥也不会只会用二维数组模拟,还模拟的漏洞百出,尊的lay了
下面是一些bug
①“一个具有“不可变性”的对象,是一个在其创建以后不能够被改变的对象。例如,不能通过对字符串的某一位置进行赋值而改变字符串。”连接为字符串的函数的返回值为新字符串,而不是在原有字符串上更改: s_join=s_join.join(re_list[i])"".join(res)
②python字符串切片长度不够就切到尾为止,不会报错
③一要注意原始列表创建的大小;二要注意开始和结束的条件,否则会出现 超出index的错误

2.大佬

看到一维数组模拟 我人直接傻掉 妈妈问我为什么跪着看电脑呜呜呜QAQ
其实就是在图中,每行字符间的间隔是不重要的,没必要维持列间的结构,只需要把字符分到每行即可

https://leetcode.cn/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/

class Solution:
    def convert(self, s: str, numRows: int) -> str:
    	#如果只有一行z,直接输出原字符串
        if numRows < 2: return s
        #几行z就建立几个字符串,第i个字符串代表第i行,字符串用一维列表存储
        res = ["" for _ in range(numRows)]
        #i代表行,也就是第i个字符串,flag表示方向,-1表示向上,1表示向下
        i, flag = 0, -1
        #遍历s中的字符
        for c in s:
        	#每次存入当前行中一个字符
            res[i] += c
            #当i=0(首行)或i=numRows - 1(尾行)时,flag反向
            if i == 0 or i == numRows - 1: flag = -flag
            #i更新
            i += flag
        #返回结果
        return "".join(res)

三、代码

1.python(二维数组模拟)

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        #字符串长度
        n=len(s)
        if(numRows==1):
            return s
        #每组字符长度
        step=2*numRows -2
        #列表生成式生成有numRows行的二维列表,列表元素为空字符串
        re_list=[["" for j in range((n//step + 1)*(numRows - 1)+1)] for i in range(numRows)]
        #第几组
        group=0

        #遍历所有字符串,步长为组的长度
        for i in range(0,n,step):
            #本组字符串
            temp=s[i:i+step]+'0'
            #本组起始位置(列),从零开始的下标
            start=group*(numRows-1)
            #遍历本组每个字符串,j是本组字符串下标
            for j in range(step):
                #判断是否已经结束,一定要注意边界条件!
                if(temp[j]=='0'):
                    break

                #放竖着的
                if(j<numRows):
                    re_list[j][start]+=temp[j]
                #放斜着的
                else:
                    #与竖着最后一个元素的横纵坐标绝对值
                    abs_len = j-numRows+1
                    #锁定坐标
                    re_list[numRows-1-abs_len][start+abs_len]+=temp[j]

            #一组已经放好
            group+=1
        #按行输出即可
        re_str=""
        for i in range(numRows):
            s_join=""
            s_join=s_join.join(re_list[i])
            re_str+=s_join
        return re_str

2.c++(一维数组模拟)

class Solution {
public:
    string convert(string s, int numRows) {
        //只有一行,直接返回
        if(numRows==1){
            return s;
        }
        //存放结果
        string re[numRows];
        for(int i = 0;i<numRows;i++){
            re[i]="";
        }
        //字符串长度
        int n=s.length();
        int row=0;
        int flag=-1;

        //遍历字符串
        for(int i=0;i<n;i++){
            re[row]+=s[i];
            if(row==0 || row==numRows-1){
                flag=-flag;
            }
            row+=flag;
        }
        //结果
        string re_str;
        for(int i = 0;i<numRows;i++){
            re_str+=re[i];
        }
        return re_str;
    }    
};

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值