算法学习之路-坚持走下去
Z字形变换
题目描述
- 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
- 比如输入字符串为
"LEETCODEISHIRING"
行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
- 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:
"LCIRETOESIIGEDHN"
。 - 请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
当我再次遇到时,仍旧不会
- 这道题目,我第一次遇到的时候,参考了答案的写法,并进行了练习。
- 但是再次遇到的时候仍旧无法独立解出,这里重新记录一下脑海运行思路。争取下次再练习的时候能够独立解出。
题目分析
- 按照题干描述,我们需要读取字符排列之后的Z字形图案
- 直观的感觉告诉我,按行读取是一种可行的方式。但是代码如何书写呢?脑海中此时有些无从下手
冷静分析
- 题干中给出当行数为3时的图案,那么行数应该为大于零的正整数
以字符串。helloworld 为例
行数为1时的图案
helloworld 输出: helloworld
行数为2
h l o o l
e l w r d 输出: hloolelwrd
行数为3
h o l
e l w r d
l o 输出: holelwrdlo
不难发现当行数为1和2的时候,情况变得十分简单
当行数为1的时候,我们每隔0个字符取一个字符进行第一行的z字形绘制
当行数为2的时候,我们每隔1个字符取一个字符进行,,,
当行数为3的时候,我们每隔3个字符取一个字符进行,,,
,,,
可以发现第一行的规律所在:假设。rows:行数。 rows*2-2 代表着隔几个字符我们取到下一个的字符索引位置
在不考虑中间字符的情况下,每一行的字符都符合此规律
以行数为3的z字形图案为例,在不考虑中间字符的情况下
每一行的字符与该行下一个字符都相距 着。 2*3-2=4个字符。综上可以实现已有的代码逻辑
public String convert(String s,int numRows) {
// 当行数为1的时候
if(numRows == 1) {
return s;
}
int len = s.length();
// 与行数相关,间隔范围
int cycle = numRows*2-2;
StringBuilder res = new StringBuilder();
// 按行读取,每一行进行访问
for (int i = 0; i < numRows; i++) {
// 每次隔 cycle 取下一个字符, j < len-1 保证不会发生越界情况
for (int j = 0; j+i < len; j+=cycle) {
// +i 代表读取的行数 +j 代表相隔的字符个数
res.append(s.charAt(j+i));
}
}
return res.toString();
}
- 但是到这里还没有处理中间字符的情况
先定义一个长度较长的字符串。 hinihaomwoshidhuilang
行数为4
h o i a
i a m h d l n
n h w s h i g
i o u
行数为5
h w u
i m o h i
n o s a l
i a h d a g
h i n
观察发现在首行和尾行,我们的图形不需要考虑中间字符的情况
当我们读取i之后需要读取下一个字符,对于行数为4的情况来说,需要隔3个字符,
总结规律:行数为4为例 隔6个字符取一个数字
i:当前行1,隔字符数3 a:6-1=5. h:6-2=4
n:当前行2,隔字符数1。
在我们的代码中。 i为当前行数,j+i 为当前位置索引,j+i+cycle 为 m 的索引下标位置
总结:
当行数为 rows 除去首尾行中间字符位置规律为
(2*rows-2)+j-i,当行数为4,那么即为6+j-i
a: 6+0-1 h: 6+6-1 l: 6+12-1
h: 6+0-2 s: 6+6-2 i: 6+12-2
可得到完整版代码
public String convert(String s,int numRows) {
if(numRows == 1) {
return s;
}
int len = s.length();
int cycle = 2*numRows-2;
StringBuilder res = new StringBuilder();
for (int i = 0; i < numRows; i++) {
for (int j = 0; j+i < len; j+=cycle) {
res.append(s.charAt(i+j));
if(i != 0 && i != numRows-1 && j+cycle-i < len) {
// 通过观察数字分布规律得到
res.append(s.charAt(j+cycle-i));
}
}
}
return res.toString();
}
回顾总结
- 我个人在练习算法题的时候经常会陷入,不会——看题解——理解题解——抄一遍题解——下次遇到——不会,的尴尬境地中
- Z字形变换这道题,详细记录思路历程,以及如何保证自己再次遇到同样或类似题目的时候能够快速解决题目
- 加油!努力进大厂