【中等】题解力扣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, intRows);

示例 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

解题思路

题目要求将字符串按Z字形(N字形)排列后按行读取。核心思路是找到每个字符在Z字形排列中的行号规律,然后按行拼接字符串。通过观察,可以发现以下规律:

  1. 周期:每个Z字形周期的长度为 cycle = 2 * (numRows - 1)(当 numRows > 1 时)。
  2. 首行和末行:每周期只有一个字符,位置为 j(起始位置)和 j + cycle(下一周期起始位置)。
  3. 中间行:每周期有两个字符,位置分别为 jj + cycle - 2 * i(其中 i 为行号)。

具体步骤:

  1. numRows = 1,直接返回原字符串。
  2. 计算周期长度 cycle = 2 * (numRows - 1)
  3. 为每一行创建一个 StringBuilder 存储字符。
  4. 遍历每一行 i(0 到 numRows-1):
    • 从起始位置 j = i 开始,每次增加一个周期长度 cycle
    • 将位置 j 的字符加入当前行。
    • 若非首行和末行,计算中间位置 mid = j + cycle - 2 * i,若未越界则加入当前行。
  5. 合并所有行的字符串并返回。

此方法时间复杂度为 O(n),每个字符仅访问一次;空间复杂度为 O(n),存储结果字符串。


代码实现(Java版)

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1) {
            return s;
        }
        int n = s.length();
        StringBuilder[] rows = new StringBuilder[numRows];
        for (int i = 0; i < numRows; i++) {
            rows[i] = new StringBuilder();
        }
        int cycle = 2 * (numRows - 1);
        for (int i = 0; i < numRows; i++) {
            int j = i;
            while (j < n) {
                rows[i].append(s.charAt(j));
                if (i != 0 && i != numRows - 1) {
                    int mid = j + cycle - 2 * i;
                    if (mid < n) {
                        rows[i].append(s.charAt(mid));
                    }
                }
                j += cycle;
            }
        }
        StringBuilder res = new StringBuilder();
        for (StringBuilder row : rows) {
            res.append(row);
        }
        return res.toString();
    }
}

代码说明

  • 周期计算cycle = 2 * (numRows - 1) 确定Z字形重复的间隔。
  • 字符分配
    • 首行和末行:每周期只添加一个字符(位置 j)。
    • 中间行:每周期添加两个字符(位置 jmid),mid 通过 j + cycle - 2 * i 计算。
  • 边界处理numRows = 1 时直接返回原字符串;mid 位置需检查越界。
  • 性能优化:每个字符仅访问一次,无冗余操作;使用 StringBuilder 数组高效构建每行字符串,最后合并。

提交详情(执行用时、内存消耗)

在这里插入图片描述
在这里插入图片描述

感谢大家的阅读,如果觉得这篇内容对你有帮助,别忘了点赞+收藏+关注哦!!大家如果想要进一步深入了解本道算法题,通过输入测试数据来了解其运算的过程,可点击文章底部名片关注后,可免费获取完整的可运行调试的Java代码

我的名片👇👇👇👇👇👇👇👇👇👇👇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值