LeetCode 6. Z 字形变换

6. Z 字形变换

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

在这里插入图片描述
链接 https://leetcode.cn/problems/zigzag-conversion/

个人思路
  1. 观察示例可以发现,字符串s的每个字符将要摆放在的行的序列为0,1,2,3,2,1,0,1,2,3···,因此这就是一个0,1,2,3,2,1的循环,也就是0,1,2,···,numRows,numRows-1,···,1的循环。
  2. 我们先来构造这样一个循环:
a = [i for i in range(0,numRows)]
b = [j for j in range(numRows-2,0,-1)]
index = a + b
  1. 接下来计算s会在index中循环多少次:构造刚好能够容纳s长度的列表
# 计算列表长度
x = len(s) // len(index)
y = len(s) % len(index)
index = index * x + index[0:y]
  1. 接下来循环,把s中的每个字符放进以index元素为key的字典,最后返回即可
    总的代码如下:
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        # 先排除一行的情况,否则后面构造列表会报错
        if numRows == 1:
            return s
        a = [i for i in range(0,numRows)]
        b = [j for j in range(numRows-2,0,-1)]
        index = a + b
        # 计算列表长度
        x = len(s) // len(index)
        y = len(s) % len(index)
        index = index * x + index[0:y]
        # 储存结果中的每一行
        haxi = {}
        for i in range(len(s)):
            haxi[index[i]] = haxi.get(index[i],'') + s[i]
        ans = ''
        for key in range(numRows):
            ans = ans+haxi.get(key,'')
        return ans   

在这里插入图片描述

官方思路
  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
        c = (n + t - 1) // t * (r - 1)
        mat = [[''] * c for _ in range(r)]
        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)

该方法比较时间可空间复杂度较高
复杂度分析

时间复杂度:O(r⋅n),其中 }r=numRows,n为字符串 s的长度。时间主要消耗在矩阵的创建和遍历上,矩阵的行数为 rr,列数可以视为 O(n)。
空间复杂度:O(r⋅n)。矩阵需要O(r⋅n) 的空间。

  1. 压缩矩阵空间

    上面方法中的矩阵有大量的空间没有被使用,能否优化呢?
    注意到每次往矩阵的某一行添加字符时,都会添加到该行上一个字符的右侧,且最后组成答案时只会用到每行的非空字符。因此我们可以将矩阵的每行初始化为一个空列表,每次向某一行添加字符时,添加到该行的列表末尾即可。

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
        return ''.join(chain(*mat))
  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
        ans = []
        for i in range(r):  # 枚举矩阵的行
            for j in range(0, n - i, t):  # 枚举每个周期的起始下标
                ans.append(s[j + i])  # 当前周期的第一个字符
                if 0 < i < r - 1 and j + t - i < n:
                    ans.append(s[j + t - i])  # 当前周期的第二个字符
        return ''.join(ans)

复杂度分析

时间复杂度:O(n),其中 nn 为字符串 s的长度。s中的每个字符仅会被访问一次,因此时间复杂度为 O(n)。
空间复杂度:O(1)。返回值不计入空间复杂度。

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/zigzag-conversion/solution/z-zi-xing-bian-huan-by-leetcode-solution-4n3u/
来源:力扣(LeetCode)

其他思路

本质上还是找规律,但代码中flag用的很妙

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows < 2: return s
        res = ["" for _ in range(numRows)]
        i, flag = 0, -1
        for c in s:
            res[i] += c
            if i == 0 or i == numRows - 1: 
               flag = -flag
            i += flag
        return "".join(res)

作者:jyd
链接:https://leetcode.cn/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/
来源:力扣(LeetCode)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值