二、字符串(44)6. Z 字形变换

6. 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.字典的键可以是整型,值可以是列表

2.字典的键如果是索引,注意范围不要越界

3.a = list()表示创建空列表

4.字符串不能通过索引取值。可以将其转为列表,再用索引取值

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        dit = {}#创建字典,字典里有numRowS个列表元素,每个列表用于存储一行元素
        #P     I    N   1:(P,I,N)
        #A   L S  I G
        #Y A   H R
        #P     I
        a = list()#最后将各行添加到a这个空列表中

        n = len(s)
        for i in range (1, numRows + 1):
            dit[i] = list()
        j = 1#第几行
        i = 0#当前的索引
        s = list(s)#转化为列表,使得可以通过索引进行遍历
        while True:
            if j == 1:#从第一行到第numRows行
                while j <= numRows:
                    dit[j].append(s[i])#添加到各行
                    j += 1
                    i += 1
                    if i == n:#全部元素都添加完后,将4个列表合并,并转化为字符串
                        for k in range(1, numRows + 1):
                            a += dit[k]
                            
                        return ''.join(a)
                j = numRows - 1
            elif j == numRows - 1:#从numRows - 1行到第2行
                while j >  1:
                    dit[j].append(s[i])
                    j -= 1
                    i += 1
                    if i == n:
                        for k in range(1, numRows + 1):
                            a += dit[k]
                        return ''.join(a)
                j = 1

官方题解:

 

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        n, r = len(s), numRows
        if r == 1 or r >= n:#一行或一列,直接输出
            return s
        t = r * 2 - 2 #周期为 r + r - 2
        c = (n + t - 1) // t * (r - 1) #C 是矩阵的列数,(n + t - 1) // t表示有几组 向上取整,* (r - 1) 每组又有(r - 1)列
        mat = [[''] * c for _ in range(r)]#每行C列,每个元素都是''
        x, y = 0, 0
        for i, ch in enumerate(s):
            mat[x][y] = ch
            if i % t < r - 1:
                x += 1
            else:
                x -= 1
                y += 1
        return ''.join(ch for row in mat for ch in row if ch)
        

 

方法二:压缩矩阵空间
方法一中的矩阵有大量的空间没有被使用,能否优化呢?

注意到每次往矩阵的某一行添加字符时,都会添加到该行上一个字符的右侧,且最后组成答案时只会用到每行的非空字符。因此我们可以将矩阵的每行初始化为一个空列表,每次向某一行添加字符时,添加到该行的列表末尾即可。

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        r = numRows
        if r == 1 or r >= len(s):
            return s

        mat = [[] for _ in range(r)]
        t, x = r * 2 - 2, 0
        for i, ch in enumerate(s):
            mat[x].append(ch)
            x += 1 if i % t < r - 1 else -1#一个周期是 r-1 + r-1
        return ''.join(chain(*mat))

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值