Java算法题: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

来源:力扣(LeetCode)
链接
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目解析

这个Z字形意思就是将字符串进行单个字符逐一拆开,然后排列成一个向左边旋转90度的Z字
举个例子:

// 比如字符串 “ABCDEFGHIJKL” 行数是 3  这里的 - 代表空字符串
A - E - I -
B D F H J L
C - G - K -
// 比如字符串 “ABCDEFGHIJKL” 行数是 4  这里的 - 代表空字符串
A - - G - -
B - F H - L
C E - I K -
D - - J - -

题目要求是这样排列之后 从上往下从左往右依次重组字符串获得新的字符串那么行数为 3 的就变成了“AEIBDFHJLCGK”,而行数为 4 的 就变成了 “AGBFHLCEIKDJ”了

分析

由此我们可以进行一下分析
当我们在二维矩阵上填写字符的时候,会向下填写 r个字符,然后向右上继续填写r − 2 个字符,最后回到第一行,因此

  • Z 字形变换的周期 t = r + r - 2 = 2 * r - 2
  • 而每一个周期需要占用 1 + r - 2

可以看到上面的例子代入公式进行计算
行数为 3 的周期为 3 + 3 - 2 = 4,可以看到确实是每个周期需要 4 个字符,而每个周期需要占用 1 + 3 - 2 = 2列,也对应上了
那么行数为 4 的就由大家自己动手算一算是否正确吧

接着往下讲
得到这些规律后
我们就需要进行进一步分析:
我们模拟一个二维矩阵进行排列,那么我们需要知道的是这个二维矩阵的行列数是多少
首先行数其实我们已经知道了,就是 numRows,那么列数该怎么去求呢

首先我们需要知道这个字符串的长度,然后根据周期去求这个列数

字符串的长度可以通过 s.length()去求得
那么用长度去除以周期可以求得一共有多少个周期
再用周期数 * 每个周期占用的列数就可以得出这个二维矩阵一共有多少列了

但是要注意最后一个周期或许不是满的,这样计算出来可能会少了一个周期,所以我们使用把最后一个周期当做完整的周期去计算

列数 c = (n + t - 1) / t * (r - 1)

有了这么多信息,我们就可以写代码实现了

方法一:模拟二维数组

public String convert(String s, int numRows) {   // n 是 该字符串的长度, r 为行数int n = s.length(), r = numRows;// 如果行数为 1 或者是行数大于等于 字符串的长度,意味着只能构成一列,所以结果还是原字符串if (r == 1 || r >= n) {return s;}// t 为 周期int t = r * 2 - 2;// c 为 二维矩阵的列数int c = (n + t - 1) / t * (r - 1);// 创建一个二维字符数组 行数为 r ,列数为 cchar[][] mat = new char[r][c];for (int i = 0, x = 0, y = 0; i < n; ++i) {// 将字符存入二维数组mat[x][y] = s.charAt(i);// 如果 第i个字符的下标 取余 周期 t  <  周期的列数,说明这一列已经满了,需要往右上方存储if (i % t < r - 1) {++x; // 向下移动} else {--x; // 向上移动++y; // 向右移动}}// 创建一个可变字符串进行读取StringBuffer ans = new StringBuffer();for (char[] row : mat) {for (char ch : row) {if (ch != 0) {ans.append(ch);}}}return ans.toString();}

运行结果:

行数为 3 的字符串‘PAYPALISHIRING’经过变形后为:PAHNAPLSIIGYIR
行数为 4 的字符串‘PAYPALISHIRING’经过变形后为:PINALSIGYAHRPI

方法二:压缩矩阵空间

可以看到上面的方法中我们有许多空字符,所以在后续读取时需要进行if(ch!=0)判断,而且这样也浪费空间,那么还有什么办法呢?
其实我们可以初始化对应行数的可变字符串数组,当这个字符属于第 n 行,我们就将它添加到对应行数的字符串的末尾,用文字说明比较抽象,我举个栗子

A - E - I -
B D F H J L
C - G - K -
假设现在是 3 行 变换后的字符串为   A E I B D F H J L C G K那么我初始化一个 长度为 3 的可变字符串数组StringBuffer[] stringBuffer= new StringBuffer[3];用下面的三条线代替_ _ _ _
_ _ _ _
_ _ _ _首先 A 是在第一行的,所以我们将 A 存入第一行A _ _ _
_ _ _ _
_ _ _ _接着是 B CA _ _ _
B _ _ _
C _ _ _重点来了,下一个字符是 D,它应该存在第几行呢?
根据上面的二维矩阵可以看出它是在第二行,所以我们直接存在第二行就行了A _ _ _
B D _ _
C _ _ _以此类推A E I _
B D F H J L
C G K _现在我们将它们每一行拼接起来就能得到 A E I B D F H J L C G K
与上面的答案是一样的,并且我们创建的是可变字符串,也没有将空字符存入,所以将空间压缩了

讲解完了原理,那么开始编写代码吧

public String convert(String s, int numRows) {// n 是 该字符串的长度, r 为行数 , t 为周期int n = s.length(), r = numRows, t = 2 * (r - 1);// 如果行数为 1 或者是行数大于等于 字符串的长度,意味着只能构成一列,所以结果还是原字符串if (r == 1 || r >= n) {return s;}// 创建一个可变长度的字符串数组,长度为 rStringBuffer[] mat = new StringBuffer[r];// 初始化这个数组for (int i = 0; i < r; ++i) {mat[i] = new StringBuffer();}for (int i = 0, x = 0; i < n; ++i) {// 将 字符 存入mat[x].append(s.charAt(i));// 如果 第i个字符的下标 取余 周期 t  <  周期的列数,说明这一列已经满了,需要往右上方存储if (i % t < r - 1) {++x; // 往下一行存储} else {--x;    // 往上一行存储}}// 创建一个新的可变字符串StringBuffer ans = new StringBuffer();// 逐行拼接for (StringBuffer row : mat) {ans.append(row);}return ans.toString();
}

总结

以上就是Z字形变换的全部解析了,感谢大家观看,如有错误或更好的解法,可以评论或私信博主进行探讨,如果觉得内容对您有帮助,麻烦点个赞支持一下博主,谢谢!

Java算法题:Z字形变换相关推荐

  1. leetcode第六题Z字形变换心得记录

    算法学习之路-坚持走下去 Z字形变换 题目描述 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行 ...

  2. 【LeetCode算法 - JAVA】6.Z字形变换

    开发工具与关键技术: C# 作者:奶糖不甜 撰写时间:2022.4.17 Java是一门面向对象的编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语 ...

  3. leetcode-第六题 Z 字形变换

    题目 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L   C   ...

  4. leetcode第六题 Z字形变换

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

  5. LeetCode刷题——Z字形变换

    目录 一.题目描述 二.题解 三.源码 一.题目描述 二.题解 三.源码 class Solution(object):def convert(self, s, numRows):"&quo ...

  6. java编写字母z算法_【Java】【每日算法/刷穿 LeetCode】6. Z 字形变换(中等)

    首页 专栏 java 文章详情 0 [每日算法/刷穿 LeetCode]6. Z 字形变换(中等) 宫水三叶发布于 今天 12:03 题目描述 将一个给定字符串 s 根据给定的行数 numRows , ...

  7. Z 字形变换 C++实现 java实现 leetcode系列(六)

    Z 字形变换  java实现 C++实现  将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 ...

  8. LeetCode刷题笔记第6题:Z字形变换

    LeetCode刷题笔记第6题:Z字形变换 想法: 要完成字符串根据给定的行数从上往下,从左到右完成Z字形排列.当只有一行时直接返回原字符串,当行数大于1时,先以行数构建一个行数数值个空字符串的列表, ...

  9. java z+_Java Z 字形变换

    – 题目:Z 字形变换 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: ...

最新文章

  1. ios app证书申请基本流程
  2. 指明方向与趋势!2019开发者技能报告出炉!!!
  3. 深度学习之caffe1——软件配置与测试
  4. ORACLE 11g R2 RAC群集堆栈的关闭过程分析
  5. qpython3h安装numpy_怎么装不上numpy?
  6. c语言抓取抖音视频,【FiddlerScript】利用Fiddler中的FiddlerScript自动抓取抖音无水印视频并且自动保存...
  7. html跨域post请求,使用fetch跨域POST请求
  8. SIP应答代码【ZT】
  9. 视频压缩编码和音频压缩编码的基本原理
  10. 人工智能研究中心快递柜——代码分析四
  11. 断食有什么好处?如何轻松断食?
  12. OP向左,SaaS向右,如何选择?
  13. PHP统计总访问量和访客数
  14. Elasticsearch 搜索条件与聚合结果再进行过滤的多重聚合查询-过滤桶的使用(六)
  15. 使用IDEA把项目上传到gitee仓库
  16. 光脚丫学LINQ(006):投影
  17. arcgis rest服务无法访问
  18. 计算机图形学实验源码_计算机图形自动可微:MIT学神微分太极框架开源,论文被ICLR接收...
  19. 浏览器的堆栈内存你知道多少
  20. linux下open函数用法,linux下open函数和creat函数

热门文章

  1. ~~因果图法示例分析
  2. ERNIE1.0 与 ERNIE2.0 论文解读
  3. 『清华ERNIE』 与 『百度ERNIE』 的爱恨情仇
  4. 网络服务器 用到的技术
  5. 分享112个JS特效动画效果,总有一款适合您
  6. es6 使用filter给对象数组去重
  7. C++11右值引用、移动语义、完美转发详解
  8. 计算机一级ppt定位,课件全国计算机一级基础知识.ppt
  9. 千亿元宇宙市场,Soul、映客的新动力
  10. C语言字符串中 char char* char[] 区别