Z 字形变换-python

leetCode第6题 Z 字形变换
链接:https://leetcode-cn.com/problems/zigzag-conversion

将一个给定字符串 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

很简单的一道题,我们来分析一下
题目要求我们需要根据给出的行数将字母进行一个Z字形的排列,然后逐行拼接成一个字符串。
首先考虑暴力算法怎么解决,然后进行优化。
首先我们需要摸清楚规律
在这里插入图片描述
不妨将Z字形进行一个拆分,将一竖到另一竖之间作为一组。
那么我们进行观察,一组中包含了row + (row-2)个元素,因为第一列占满,其余一列只放一个元素,那么一组就是 2(row-1)个元素。我们求出给定字符串的长度,然后除以一组的个数就能得出我们需要多少个组。
那么一组有多少列呢?显然时 1 + row -2 = row -1列,这样组数 × \times ×一组的列数 = 总共列数。
这样我们就可以得出我们用来排列的二维列表有多大。

接下来定义r,c两个坐标表明我们需要将元素排在列表的位置。
逐个取出字符串的元素填入对应的位置。
关键是r,c怎么变化。
当在每一组的第一列的时候,c时不变的,让r+1,将这一列填满。当这一竖填满后,要将r向上移动,c向右移动,知道下一竖。那么我们怎么定义到了Z字的那一竖呢?只要当前的列数c%(row -1)==0就意味着我们到了下一组。
然后不断重复直到字符串的所有元素被取完。

## python3
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        num =int( len(s) / (2 * (numRows - 1)) ) + 1
        numColunms = (numRows - 1) * num
        res = [ [0 for i in range(numColunms)] for i in range(numRows)]
        r,c = 0,0
        for i in range(len(s)):
            x = s[i]
            res[r][c] = x
            if c % (numRows-1) == 0:
                r += 1
                if r == (numRows):
                    c += 1
                    r -= 2
            else:
                r -= 1
                c += 1
        res_str = ""
        for i in range(len(res)):
            for j in range(len(res[0])):
                if res[i][j] != 0:
                    res_str += res[i][j]
        return  res_str

这样写的执行效率很低,效果很不理想,我们需要进行优化。

我们观察r,c的变化,发现,r增加到最底部时就要一格一格返回最顶部,而c只是在不同的时机一直向右移动。
在上一种写法中,我们定义的res列表用大量的0元素填充,这些零和指针c是不是可以去掉呢?
python提供了列表灵活的操作方式,c只会向右移,元素只会在右边添加,append()方法就能实现,而且我们也不需要知道列表到底应该有多少列。
我们通过r的变化,在合适的位置将元素append()进去就行了。
当r没到底部时就一直自增,触底了就反弹,通过r指针告诉我们在哪一行append就行了。

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        res,row,i = [[] for i in range(numRows)],0,0
        while i < len(s):
            if row == numRows:
                row -= 1
                while row > 1 and i < len(s):
                    row -= 1
                    res[row].append(s[i])
                    i += 1
                row -= 1
                continue
            res[row].append(s[i])
            row += 1
            i += 1
        str1 = ''
        for each in res:
            for each1 in each:
                str1 += str(each1)
        return str1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

unseven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值