LeetCode6 Z字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
在这里插入图片描述
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例1

输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”

示例2

输入:s = “PAYPALISHIRING”, numRows = 4
输出:“PINALSIGYAHRPI”
解释
在这里插入图片描述

示例3

输入:s = “A”, numRows = 1
输出:“A”

分析(1

第一次想的十分复杂
1.基于题目给的要求,我的首先想法是需要开辟一个空间对需要的内容进行保存,我们才能按顺序输出(参照上面的排列情况解释)。那么毋庸置疑,需要使用一个二维数组。那么需要多大的呢?
2.本人根据“找规律”的方法得出了数组的行数和列数:
row = a × numRows − ( a − 1 ) \text{row} = a \times \text{numRows} - (a -1) row=a×numRows(a1)
column = numRows \text{column} = \text{numRows} column=numRows
其中, a = ⌈ ( n − 1 ) / numRows ⌉ a = \lceil(n-1) / \text{numRows}\rceil a=(n1)/numRows
在这里插入图片描述
3.从第一列开始,依次将字符向下填入(增加行),并设定此时状态为 1 1 1。若填满,状态改变为 − 1 -1 1,此时需要依次向右上方填入(减少行并增加列)。若此时行数为第二行,改变状态为 1 1 1 ,从下一列开始,继续进行以上的操作,直到最后一个字符被填入。
4.如下图所示,每次类似于做一个“竖提”操作。
在这里插入图片描述

code1

import math

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        n = len(s)
        if numRows > n or numRows == 1:
            return s
        temp = math.ceil((n - 1) / numRows)
        c = temp * numRows - (temp - 1)
        tempArray = [[False for _ in range(c)] for _ in range(n)]
        k = 0
        flag = 1
        j = 0
        while j <= c-1:
            if k > n - 1:
                break
            if flag == 1:
                for i in range(numRows):
                    if k > n - 1:
                        break
                    tempArray[i][j] = s[k]
                    k += 1
                    if i == numRows - 1:
                        j += 1
                flag = -1

            if flag == -1:
                for i in range(numRows - 2, 0, -1):

                    if k > n - 1:
                        break
                    tempArray[i][j] = s[k]
                    j += 1
 **加粗样式**                   k += 1
                    if i == 1:
                        j += 1
                flag = 1

        result = []
        for i in range(numRows):
            for j in range(c):
                if not tempArray[i][j] == False:
                    result.append(tempArray[i][j])
        return "".join(result)



这个代码能实现第一部分实例,但字符串太长就会出错。于是我进行了第二次分析

分析(2

1.我想我的方法应该是没啥大问题,那就应该是开辟的空间有问题。Code1中开辟的空间肯定存在冗余和浪费。因为我存储时也是按照“Z字形”进行存储。但其实不难发现,以下两种存储方式是一样的:
在这里插入图片描述
可以很明显看到少了一列。即我们只用不填那一列的头和尾就可以了。
2.而且对于这种排列情况,我们把它当作是 numRow \text{numRow} numRow 个列表( List \text{List} List),这样就会省去很多的空间。
3.其余思想与分析1类似。

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        n = len(s)
        a = []
        for i in range(numRows):
            a.append([])
        i = 0
        k = 0
        while i <= n-1:
            if k % 2 == 0:
                for j in range(numRows):
                    a[j].append(s[i])
                    i += 1
                    if i > n-1:
                        break
                if j == numRows - 1:
                    k += 1
            else:
                for j in range(numRows - 2, -1, -1):
                    a[j].append(s[i])
                    i += 1
                    if i > n-1:
                        break
                if j == 1 or j == 0:
                    k += 1
        b = []
        for i in range(numRows):
            b += a[i]
            print(b)
        return "".join(b)

成功通过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值