Leetcode0721:6、Z字形变换

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

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

L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。

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

string convert(string s, int numRows);
示例 1:

输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”
示例 2:

输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:

L D R
E O E I I
E C I H N
T S G

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zigzag-conversion
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法1: 最优解法

方法一:按行排序 十分巧妙地解法
思路

通过从左向右迭代字符串,我们可以轻松地确定字符位于 Z 字形图案中的哪一行。

算法

我们可以使用 \text{min}( \text{numRows}, \text{len}(s))min(numRows,len(s)) 个列表来表示 Z 字形图案中的非空行。

从左到右迭代 ss,将每个字符添加到合适的行。可以使用当前行和当前方向这两个变量对合适的行进行跟踪。

只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。

class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows == 1:
            return s
        res = ['']*min(len(s),numRows)
        n = len(s)
        curRows = 0
        flag = False
        for i in s:
            res[curRows] += i
            if curRows == 0 or curRows == numRows -1:
                #判断改变方向
                flag = not flag
            if flag:
                #从上到下
                curRows += 1
            else:
                #从下到上
                curRows -= 1
        return ''.join(res)

解法2: 找规律解法,更容易想到的解法
思路

按照与逐行读取 Z 字形图案相同的顺序访问字符串。

算法

首先访问 行 0 中的所有字符,接着访问 行 1,然后 行 2,依此类推…

对于所有整数 kk,

行 0 中的字符位于索引k(2⋅numRows−2) 处;
行 numRows-1 中的字符位于索引 k(2⋅numRows−2)+numRows−1 处;
内部的 行 i 中的字符位于索引k(2⋅numRows−2)+i 以及 (k+1)(2⋅numRows−2)−i 处;
时间复杂度:O(n)O(n),其中 n == \text{len}(s)n==len(s)。每个索引被访问一次。
空间复杂度:O(n)O(n)。对于 C++ 实现,如果返回字符串不被视为额外空间,则复杂度为 O(1)O(1)。

class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows == 1:
            return s
        res = []
        n = len(s)
        cyclelenLen = 2*numRows-2
        i = 0
        while i < numRows :
            j = 0
            while j+i < n:
                res.append(s[j+i])
                if i != 0 and i != numRows-1 and j+cyclelenLen-i < n:
                    res.append(s[j+cyclelenLen-i])
                j = j+cyclelenLen
            i += 1
        return ''.join(res)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值