Java算法题:Z字形变换
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字形变换相关推荐
- leetcode第六题Z字形变换心得记录
算法学习之路-坚持走下去 Z字形变换 题目描述 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行 ...
- 【LeetCode算法 - JAVA】6.Z字形变换
开发工具与关键技术: C# 作者:奶糖不甜 撰写时间:2022.4.17 Java是一门面向对象的编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语 ...
- leetcode-第六题 Z 字形变换
题目 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L C ...
- leetcode第六题 Z字形变换
题目 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下 ...
- LeetCode刷题——Z字形变换
目录 一.题目描述 二.题解 三.源码 一.题目描述 二.题解 三.源码 class Solution(object):def convert(self, s, numRows):"&quo ...
- java编写字母z算法_【Java】【每日算法/刷穿 LeetCode】6. Z 字形变换(中等)
首页 专栏 java 文章详情 0 [每日算法/刷穿 LeetCode]6. Z 字形变换(中等) 宫水三叶发布于 今天 12:03 题目描述 将一个给定字符串 s 根据给定的行数 numRows , ...
- Z 字形变换 C++实现 java实现 leetcode系列(六)
Z 字形变换 java实现 C++实现 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 ...
- LeetCode刷题笔记第6题:Z字形变换
LeetCode刷题笔记第6题:Z字形变换 想法: 要完成字符串根据给定的行数从上往下,从左到右完成Z字形排列.当只有一行时直接返回原字符串,当行数大于1时,先以行数构建一个行数数值个空字符串的列表, ...
- java z+_Java Z 字形变换
– 题目:Z 字形变换 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: ...
最新文章
- ios app证书申请基本流程
- 指明方向与趋势!2019开发者技能报告出炉!!!
- 深度学习之caffe1——软件配置与测试
- ORACLE 11g R2 RAC群集堆栈的关闭过程分析
- qpython3h安装numpy_怎么装不上numpy?
- c语言抓取抖音视频,【FiddlerScript】利用Fiddler中的FiddlerScript自动抓取抖音无水印视频并且自动保存...
- html跨域post请求,使用fetch跨域POST请求
- SIP应答代码【ZT】
- 视频压缩编码和音频压缩编码的基本原理
- 人工智能研究中心快递柜——代码分析四
- 断食有什么好处?如何轻松断食?
- OP向左,SaaS向右,如何选择?
- PHP统计总访问量和访客数
- Elasticsearch 搜索条件与聚合结果再进行过滤的多重聚合查询-过滤桶的使用(六)
- 使用IDEA把项目上传到gitee仓库
- 光脚丫学LINQ(006):投影
- arcgis rest服务无法访问
- 计算机图形学实验源码_计算机图形自动可微:MIT学神微分太极框架开源,论文被ICLR接收...
- 浏览器的堆栈内存你知道多少
- linux下open函数用法,linux下open函数和creat函数