zoukankan      html  css  js  c++  java
  • LeetCode --- 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);
    示例2:
    输入: s = "LEETCODEISHIRING", numRows = 4
    输出: "LDREOEIIECIHNTSG"
    解释:

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

    解题方法
    对于n行的Z字形字符序列,可以发现每间隔(2*n-2)个序号为一个周期,假设考虑字符串序号从1开始向后排列,那么

    第2n-1个字符和第1个字符都在第一行、
    第2
    n个字符和第2个字符都在第二行、
    第2n+1个字符和第3个字符都在第三行、
    ……
    第3
    n-2个字符和第n个字符都在第n行。

    Z字形字符序列的每一行都可以看做一个列表,初始化一个列表res = [[],[],[],...,[]],列表有n个元素,每个元素都是一个子列表,子列表内容是按顺序出现在对应行的字符。
    那么关键需要找到字符串每个序号对应Z字形字符序列的行号,定义一个函数为int Z_func(int numRows, int index);,返回字符numRows[index-1]在字符串numRows对应Z字形字符序列的行号(1~numRows)。
    n=5 序号示意图
    上图假设n=5,序号16先被模8(2n-2)得到0,但我们期望它序号是8(8 = 0 = 16 mod 8)以方便后面判断,用8-n取绝对值得到3,表示点16与Z字形最下层的距离distance,然后再用n反向减去distance取绝对值得到5-3=2,就表示了行号2。
    再假设序号为15的时候先被模8(2
    n-2)得到7,用7-n取绝对值得到2,表示点15与Z字形最下层的距离distance,然后再用n反向减去distance取绝对值得到5-2=3,就表示了行号3。
    此外还有两种特殊情况:行数n为1字符串s长度为1,此时都只需要直接返回字符串s就可以。
    程序

    class Solution:
        def Z_func(self, numRows: int, index: int) -> int:
            maxlen = 2*numRows - 2
            index %= maxlen
            if index == 0:
                index += maxlen
            distance = abs(numRows - index)
            return abs(numRows - distance)
        
        def convert(self, s: str, numRows: int) -> str:
            if len(s) == 1 or numRows == 1:
                return s
            res = []
            for i in range(numRows):
                res.append([])
            for index,value in enumerate(s):
                line = self.Z_func(numRows, index + 1)
                res[line-1].append(value)
            return "".join([j for i in res for j in i])
    
  • 相关阅读:
    LOJ 6089 小Y的背包计数问题 —— 前缀和优化DP
    洛谷 P1969 积木大赛 —— 水题
    洛谷 P1965 转圈游戏 —— 快速幂
    洛谷 P1970 花匠 —— DP
    洛谷 P1966 火柴排队 —— 思路
    51Nod 1450 闯关游戏 —— 期望DP
    洛谷 P2312 & bzoj 3751 解方程 —— 取模
    洛谷 P1351 联合权值 —— 树形DP
    NOIP2007 树网的核
    平面最近点对(加强版)
  • 原文地址:https://www.cnblogs.com/Higgerw/p/13458570.html
Copyright © 2011-2022 走看看