美文网首页刷穿 LeetCode
【刷穿 LeetCode】6. Z 字形变换(中等)

【刷穿 LeetCode】6. Z 字形变换(中等)

作者: 水三叶的刷题日记 | 来源:发表于2021-02-03 16:43 被阅读0次

    点击 这里 可以查看更多算法面试相关内容~

    题目描述

    将一个给定字符串 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 = 输出:"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

    直观规律解法

    本题可以当成模拟题来做。

    对需要打印的行 i 进行遍历,每一行的第一个字符可以直接确定:原字符开头的第 i 个字符。

    然后计算出每行下一个字符的偏移量,这里需要分情况讨论:

    • 对于第一行和最后一行:偏移量固定,不随着 Z 的方向改变

    • 对于其他行:偏移量随着 Z 的方向发生变化

    class Solution {
        public String convert(String s, int r) {
            int n = s.length();
            if (n == 1 || r == 1) return s;
    
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < r; i++) {
                if (i == 0 || i == r - 1) {
                    int j = i;
                    int rowOffset = (r - 1) * 2 - 1;
                    while (j < n) {
                        sb.append(s.charAt(j));
                        j += rowOffset + 1;
                    }
                } else {
                    int j = i;
    
                    int topRow = i;
                    int topOffset = topRow * 2 - 1;
    
                    int bottomRow = r - i - 1;
                    int bottomOffset = bottomRow * 2 - 1;
    
                    boolean flag = true;
                    while (j < n) {
                        sb.append(s.charAt(j));
                        j += flag ? bottomOffset + 1 : topOffset + 1;
                        flag = !flag;
                    }
                }
            }
            return sb.toString();
        }
    }
    

    时间复杂度:分别对 s 中的每个字符进行打印。复杂度为 O(n)

    空间复杂度:O(1)


    数学规律解法

    在平时的练习中,对于这种找规律的题,当我们使用直观的思路推理出一个解法之后,可以尝试从数学的角度上去分析。

    例如本题,我们可以不失一般性的将规律推导为「首项」和「公差公式」。

    这通常能够有效减少一些判断。

    分情况讨论:

    • 对于第一行和最后一行:公差为 2 * (n − 1) 的等差数列,首项是 i

    • 对于其他行:两个公差为 2 * (n − 1) 的等差数列交替排列,首项分别是 i2 * n − i − 2

    class Solution {
        public String convert(String s, int r) {
            int n = s.length();
            if (n == 1 || r == 1) return s;
    
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < r; i++) {
                if (i == 0 || i == r - 1) {
                    int pos = i;
                    int offset = 2 * (r - 1);
                    while (pos < n) {
                        sb.append(s.charAt(pos));
                        pos += offset;
                    }
                } else {
                    int pos1 = i, pos2 = 2 * r - i - 2;
                    int offset = 2 * (r - 1);
                    while (pos1 < n || pos2 < n) {
                        if (pos1 < n) {
                            sb.append(s.charAt(pos1));
                            pos1 += offset;
                        }
                        if (pos2 < n) {
                            sb.append(s.charAt(pos2));
                            pos2 += offset;
                        }
                    }
                }
            }
            return sb.toString();
        }
    }
    

    时间复杂度:分别对 s 中的每个字符进行打印。复杂度为 O(n)

    空间复杂度:O(1)


    总结

    这种”找规律“的模拟题,和小学奥数题十分类似。要提高自己的做题水平,需要坚持两个方向:

    1. 自己多在纸上画图找规律,这种题没有什么通用解法

    2. 多做题,尽量对每种”规律“都有所接触


    最后

    这是我们「刷穿 LeetCode」系列文章的第 No.6 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。

    在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

    由于 LeetCode 的题目随着周赛 & 双周赛不断增加,为了方便我们统计进度,我们将按照系列起始时的总题数作为分母,完成的题目作为分子,进行进度计算。当前进度为 6/1916

    为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:Github 地址 & Gitee 地址

    在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和一些其他的优选题解。

    相关文章

      网友评论

        本文标题:【刷穿 LeetCode】6. Z 字形变换(中等)

        本文链接:https://www.haomeiwen.com/subject/gysrtltx.html