Leetcode算法——6、之字形转换

76 篇文章 1 订阅

题目

The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this:
P A H N
A P L S I I G
Y I R
And then read line by line: “PAHNAPLSIIGYIR”
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);

给定行数,字符串”PAYPALISHIRING”可以写成之字形:

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

然后,一行一行地读:”PAHNAPLSIIGYIR”
要求编写一个函数,输入一个字符串和行数,改写为之字形后,输出按行读的结果。

示例:
Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P     I    N
A   L S  I G
Y A   H R
P     I

思路

1、模拟法

先初始化一个二维数组,当做一个平面,然后按照之字形规则依次摆放每个元素,相当于用画笔画出之字形,然后按行读取即可。

2、直接输出法

可以找到规律,每 2*numRows-2 一个周期。因此,可以根据当前元素的下标在整个周期中的位置,来计算下一个元素的下标。

0     6      12 
1   5 7   11 13
2 4   8 10
3     9

具体包括两部分:

  • 第一行和最后一行的元素总是相差一个周期,如 0、6、12。
  • 对于中间行,一个元素和下一个元素的下标之和,等于周期的整数倍,如 1+5=6,5+7=12。至于整数倍是多少,就要看当前元素是位于竖行还是斜行了。

python实现

# -*- coding: utf-8 -*-

def convert(s, numRows):
    """
    :type s: str
    :type numRows: int
    :rtype: str

    模拟法。
    先初始化一个二维数组,当做一个平面,然后按照之字形规则依次摆放每个元素,最后按行读取。
    为了方便,我们将之字形由竖版改为横版:
    PAYP
      A
     L
    ISHI
      R
     I
    NG

    """

    if len(s) <= numRows or numRows == 1:
        return s

    # 画出之字形
    plot = []
    direction = 1 # 画笔方向,1为右,0为左0
    plot.append(['']*numRows) # 初始化第一行
    i = 0
    j = -1
    for idx in range(len(s)):
        if direction == 1: # 向右,则行不变,列+1
            j += 1
            plot[i][j] = s[idx]
            if j == numRows - 1: # 到头了,则往回走
                direction = 0
        else: # 向左,则行+1,列-1
            plot.append(['']*numRows) # 新添加一行
            i += 1
            j -= 1
            plot[i][j] = s[idx]
            if j == 0:
                direction = 1
    # 按列输出
    output = ''
    for j in range(numRows):
        for i in range(len(plot)):
            output += plot[i][j]
    return output

def convert2(s, numRows):
    """
    :type s: str
    :type numRows: int
    :rtype: str

    直接输出法。
    可以找到规律,每 2*numRows-2 一个周期。

    0     6      12 
    1   5 7   11 13
    2 4   8 10
    3     9

    """

    if len(s) <= numRows or numRows == 1:
        return s

    period = 2*numRows-2
    output = s[0]
    i = 0
    count = 1
    while(count < len(s)):
        # 寻找下一个
        rest = i % period
        if rest == 0 or rest == numRows - 1: # 位于第一行或最后一行
            i += period    
        elif rest <  numRows - 1: # 位于竖行
            i += (numRows - rest - 1) * 2
        else: # 位于斜行
            i += (period - rest) * 2
        # 如果溢出则换行
        if i >= len(s):
            if rest <= numRows - 1:
                i = rest + 1
            else:
                i = period - rest + 1

        # 赋值
        output += s[i]
        count += 1

    return output

if '__main__' == __name__:
    s = 'ABCD'
    n = 3
    print(convert(s, n))
    print(convert2(s, n))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值