一、LeetCode 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, int numRows);
示例:
输入: s = "PAYPALISHIRING", numRows = 3 输出: "PAHNAPLSIIGYIR"
二、解题分析
这道算法题是非常有意思的,因为大多数的同学在第一次看到的时候根本就弄不明白,这个到底是在干啥。
到底是弄啥类?!
分析这道题时有一个诀窍,就是要把这个题目介绍中的Case
当成古代的武林秘籍
看,不同于现在文字横写的方式,古代武林秘籍是采用垂直竖
写的方式。
如果换个视角,采用竖
着,一列一列来来看题目,表现为:
- 从字符串
s
中取出一个放入当前行,再次取出一个放入下一行,重复这个行为;
- 直到
numRows - 1
行,放置完成后;
- 接下来该调整方向,往上一行放一个;
- 继续向上,直到第0行,调整方向,往下一行放一个。
同时要考虑特殊的情况,比如:
- 只需要1行时,直接返回字符串即可。
- 当
s.length <= numRows
即字符串长度小于行数时,也可以直接返回当前字符串。
基于以上的分析,我们来看代码的实现:
/** * @param {string} s * @param {number} numRows * @return {string} */ var convert = function(s, numRows) { // 特殊Case判定 if (s.length < numRows || numRows === 1) { return s; } // 定义数组rows,对应存储每一行的字符串 const rows = [] // 使用变量i,表示rows的下标,代表了每一行 let i = 0; // 使用变量j,表示字符串s的下标 let j = 0; // 定义当前的填充字符的方向,-1表示向上,1表示向下 // 注意这里的初始值设置为-1,有特殊作用 let dir = -1; // 遍历字符串,将每一个字符放入到对应的每一行中 while (j < s.length) { // 要注意,对应的每一个i行,都是要拼接上最新的字符。 // 注意初rows[i]是否存在 rows[i] = rows[i] ? rows[i] += s[j] : s[j]; // 调整方向判定条件:第0行以及第numRows - 1行 if (i === 0 || i === numRows - 1) { // 如果调整方向呢,当前值 *= -1即发生反向 dir *= -1; } // 当前行数发生变化 i += dir; // 变量j发生变化,继续遍历子串s j++; } // 将数组中的每行字符串再次进行拼接,并返回 return rows.join(''); };
网络异常,图片无法展示
|
三、总结
整体来看,这道算法题的问题主要集中于如何理解这个Z
字型展示的问题,分析展示的特点。得出展示的规律就好理解这个问题了。
当然解决这个问题的算法有很多种,比如去观察每一行字母的下标规律,出现的特点,也是可以计算的。 欢迎大家多多动手尝试。
TIPS:
在JS中,我们经常使用 *= -1
的形式,来调整方向,尤其是在动画相关实现中。
算法-从菜鸟开始,而无止境。与君共勉!