[20210507]LeetCode自由练习 - 6. Z 字形变换

题目描述 【中等】

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

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

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);

示例 1:
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:

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

示例 3:

输入:s = "A", numRows = 1
输出:"A"

提示:
1 <= s.length <= 1000
s 由英文字母(小写大写)、',''.' 组成
1 <= numRows <= 1000

题目地址:地址


正式分析

这个题很像是小学时候的动脑筋的题目,找到规律就可以编写对应代码了
我们看示例1的字符串排位:

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

虽然说是按Z字形排,但实际上按规律来讲,是只写了半个的Z字,即开头 P A Y P后,所有的字符走向都是按照这个半个Z字排序的,因此掌握了这个规律,代码就好写了

根据规律,每一组字符是在 2 * numRows - 2 时分割,我们在循环时取余即可获得其相对下标 absIndex ,然后再根据规律,获取实际 index,放到初始化好有 numRows 行的二维数组中,最终拼接即可


具体代码

function convert(s: string, numRows: number): string {
    const dividedBy = numRows * 2 - 2
    const rows = new Array(numRows).fill(0).map(() => new Array())
    const length = s.length

    if (s.length === 1 || numRows === 1) return s

    for (let i = 0; i < length; i++) {
        const absIndex = i % dividedBy

        let index

        if (absIndex < numRows) {
            index = absIndex
        } else {
            index = dividedBy - absIndex
        }

        rows[index].push(s[i])
    }

    return rows.map(item => item.join('')).join('')
};

TS AC,执行用时:116 ms, 在所有 TypeScript 提交中击败了 69.78% 的用户
注:执行用时有波动


最后

特别提示:

new Array(n).fill() 时,如果是以 空数组 初始化,一定不能直接将 [] 填入,否则 js 中会以 地址引用 的方式初始化这个数组,最终导致结果有误

如果我在哪里写的有问题,欢迎指出,共同进步,谢谢阅读~

你可能感兴趣的:(算法,leetcode,字符串,算法)