ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

字符串题目:Z 字形变换

2021-12-09 18:02:01  阅读:198  来源: 互联网

标签:direction 题目 字形 rowIndex StringBuffer texttt numRows textit 字符串


文章目录

题目

标题和出处

标题:Z 字形变换

出处:6. Z 字形变换

难度

4 级

题目描述

要求

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

比如输入字符串为 "PAYPALISHIRING" \texttt{"PAYPALISHIRING"} "PAYPALISHIRING",行数为 3 \texttt{3} 3 时,排列如下:

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

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

请你实现这个将字符串进行指定行数变换的函数:

string   convert(string   s,   int   numRows); \texttt{string convert(string s, int numRows);} string convert(string s, int numRows);

示例

示例 1:

输入: s   =   "PAYPALISHIRING",   numRows   =   3 \texttt{s = "PAYPALISHIRING", numRows = 3} s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR" \texttt{"PAHNAPLSIIGYIR"} "PAHNAPLSIIGYIR"

示例 2:

输入: s   =   "PAYPALISHIRING",   numRows   =   4 \texttt{s = "PAYPALISHIRING", numRows = 4} s = "PAYPALISHIRING", numRows = 4
输出: "PINALSIGYAHRPI" \texttt{"PINALSIGYAHRPI"} "PINALSIGYAHRPI"
解释:

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

示例 3:

输入: s   =   "A",   numRows   =   1 \texttt{s = "A", numRows = 1} s = "A", numRows = 1
输出: "A" \texttt{"A"} "A"

数据范围

  • 1 ≤ s.length ≤ 1000 \texttt{1} \le \texttt{s.length} \le \texttt{1000} 1≤s.length≤1000
  • s \texttt{s} s 由英文字母(小写和大写)、 ‘,’ \texttt{`,'} ‘,’ 和 ‘.’ \texttt{`.'} ‘.’ 组成
  • 1 ≤ numRows ≤ 1000 \texttt{1} \le \texttt{numRows} \le \texttt{1000} 1≤numRows≤1000

解法

思路和算法

首先考虑最简单的情形:当 numRows = 1 \textit{numRows}=1 numRows=1 时,将字符串 s s s 按照 Z 字形排列只有 1 1 1 行,且字符顺序不变,因此在 Z 字形变换之后的字符串仍然是 s s s,直接返回 s s s。

当 numRows ≥ 2 \textit{numRows} \ge 2 numRows≥2 时,Z 字形排列会有多行。在生成 Z 字形排列时,需要从左到右遍历字符串 s s s,对于每个字符,计算得到该字符位于 Z 字形排列的哪一行,然后将该字符拼接到所在行。

每个字符在 Z 字形排列中的行下标为从 0 0 0 增加到 numRows − 1 \textit{numRows}-1 numRows−1,然后减少到 0 0 0,重复在该范围内变化。因此需要维护行下标 rowIndex \textit{rowIndex} rowIndex 和变化方向 direction \textit{direction} direction,初始时 rowIndex = 0 \textit{rowIndex}=0 rowIndex=0, direction = 1 \textit{direction}=1 direction=1。遍历 s s s 的每个字符时,将该字符拼接到下标为 rowIndex \textit{rowIndex} rowIndex 的行,然后将 rowIndex \textit{rowIndex} rowIndex 的值增加 direction \textit{direction} direction,则更新后的 rowIndex \textit{rowIndex} rowIndex 为下一个字符应该拼接到的行的下标。由于行下标的取值范围是 [ 0 , numRows − 1 ] [0, \textit{numRows}-1] [0,numRows−1],因此当更新后的 rowIndex \textit{rowIndex} rowIndex 为 0 0 0 或 numRows − 1 \textit{numRows}-1 numRows−1 时,需要将 direction \textit{direction} direction 取相反数,表示下次行下标的更新需要往相反方向移动。

对 s s s 遍历结束之后,即可得到 Z 字形排列的每一行,将每一行拼接之后,即可得到 Z 字形变换后的结果。

具体实现方面,由于涉及到字符串的拼接,因此使用 StringBuffer \texttt{StringBuffer} StringBuffer 实现。创建长度为 numRows \textit{numRows} numRows 的 StringBuffer \texttt{StringBuffer} StringBuffer 类型数组,该数组的每个元素对应 Z 字形排列的每一行。在拼接每一行得到最终答案时,同样使用 StringBuffer \texttt{StringBuffer} StringBuffer 类型进行拼接。

还有一个可以优化的点。由于 Z 字形排列的每一行都至少有一个字符,因此 Z 字形排列的行数不会超过 s s s 的长度。当 s s s 的长度为 n n n 时,Z 字形排列的行数为 min ⁡ ( numRows , n ) \min(\textit{numRows}, n) min(numRows,n),因此在生成 Z 字形排列之前,令 numRows = min ⁡ ( numRows , n ) \textit{numRows} = \min(\textit{numRows}, n) numRows=min(numRows,n),可以达到优化的效果。

代码

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1) {
            return s;
        }
        int length = s.length();
        numRows = Math.min(numRows, length);
        StringBuffer[] rows = new StringBuffer[numRows];
        for (int i = 0; i < numRows; i++) {
            rows[i] = new StringBuffer();
        }
        int rowIndex = 0, direction = 1;
        for (int i = 0; i < length; i++) {
            rows[rowIndex].append(s.charAt(i));
            rowIndex += direction;
            if (rowIndex == 0 || rowIndex == numRows - 1) {
                direction = -direction;
            }
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < numRows; i++) {
            sb.append(rows[i]);
        }
        return sb.toString();
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串 s s s 的长度。创建 StringBuffer \texttt{StringBuffer} StringBuffer 类型的数组并初始化元素需要 O ( numRows ) O(\textit{numRows}) O(numRows) 的时间,生成 Z 字形排列和拼接得到 Z 字形变换后的结果各需要 O ( n ) O(n) O(n) 的时间,由于会对 numRows \textit{numRows} numRows 预处理确保 numRows ≤ n \textit{numRows} \le n numRows≤n,因此总时间复杂度是 O ( n ) O(n) O(n)。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是字符串 s s s 的长度。Z 字形排列的结果需要 O ( n ) O(n) O(n) 的空间存储,Z 字形变换后的结果也需要 O ( n ) O(n) O(n) 的空间存储。由于 Java 中的 String \texttt{String} String 类型的对象不可变,因此存储 Z 字形变换后的结果的 O ( n ) O(n) O(n) 空间无法省略。

标签:direction,题目,字形,rowIndex,StringBuffer,texttt,numRows,textit,字符串
来源: https://blog.csdn.net/stormsunshine/article/details/120242483

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有