1. Z字形变换

题目描述

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

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

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。

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

示例二
输入:s = “PAYPALISHIRING”, numRows = 4
输出:“PINALSIGYAHRPI”
解释:

P    I	  N 
A  L S  I G 
Y A	 H R 
P	 I

解题思路

暴力解法。观察z字形排列的规律,每列可以看成一个键值对,即将每列的字符串作为字典的value,列数作为key,且给value添加空格,每个空格都占一个字符的位置,使得字典的value长度一致。而返回的结果字符串即字典的每一个值的对应位置的不为空格的字符。

代码实现

# python3
import math
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        # 当输入字符串为1时,直接返回
        if len(s)==1:
            return s
        # 添加的空格数与numRows的关系
        add = numRows-2
        x = 0
        new_s=""
        i = 0
        # 遍历字符串的步长 
        step = add+numRows
        if step == 0:
            step = 1
        for i in range(0,len(s),step):
            # 按步长正常遍历时,需要添加空格的位置
            new_s = new_s+s[i:i+numRows]+" "*add
            print(f"new_s:{new_s}")
            # 观察z字形的规律,每隔step个字符后会有numRows-2个字符需要加空格
            while x<numRows-2:
                new_s = new_s+s[i+numRows+x:i+numRows+x+1]+" "*add
                x+=1
            x=0
        # 将新的字符串分割为numRows个子字符串,放入字典中
        my_dict = {i:new_s[i*numRows:i*numRows+numRows] for i in range(math.ceil(len(new_s)/numRows))} 
        # 向上取整的目的是,当numRows大于输入字符串整除numRows的结果时,不会丢失零散的子字符串

        # flag用于定位每个子字符串的单个字符位置,即z字形的第flag+1行
        flag = 0
        res=""
        # 循环numRows次
        u = 0
        # strip用于去除字典中无意义的键值对
        my_dict2 = {k: v for k, v in my_dict.items() if v.strip()}
        
        while u<numRows:
            for key in my_dict2.keys():
                # 防止flag溢出
                if flag>=len(my_dict2[key]):
                    break
                if my_dict2[key][flag:flag+1]!=" ":
                    res += my_dict2[key][flag]
            u+=1
            flag+=1
        return res

复杂度

时间复杂度:

O(n^2)

空间复杂度:

O(n)

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值