Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
编程世界总是离不了算法
最近在看框架源码时,会有很多算法的实现逻辑,有时候会感到吃力
于是决定蹭着假期,加强算法和数据结构相关的知识
那怎么提升呢?
其实我知道算法这东西没有捷径,多写多练才能提升,于是我开启我的LeetCode刷题之旅
第一阶段目标是:200道,每天1到2篇
为了不乱,本系列文章目录分为三部分:
- 今日题目:xxx
- 我的思路
- 代码实现
今天题目:2016. 增量元素之间的最大差值
将一个给定字符串 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
我的思路
两种解法,第一种比较好理解,第二种比较精简效率也更高但是理解起来有点麻烦\
第一种思路就是通过两个变量,一个记录当前的前进方向是向上还是向下,另一个记录当前在第几行的索引,循环往复就行
代码实现
/**
* @param {string} s
* @param {number} numRows
* @return {string}
*/
var convert = function (s, numRows) {
if (numRows === 1) return s // 如果只有一行直接返回就行了
let arr = new Array(numRows).fill('') // 创建一个数组,用来存储每一行的结果
let down = true // 定义方向是否向下
let row = 0 // 定义当前行数,从 0 开始向下循环
for (let i = 0; i < s.length; i++) { // 遍历 s
arr[row] += s[i] // 拼接当前字母到arr中对应的位置上
if (down) { // 如果当前向下,行数加一,下个字符添加到下一行,否则相反,不需要考虑边界
row++
} else {
row--
}
if (row === numRows - 1) { // 在这统一处理越界情况
down = false // 如果触碰到最后一行,转向上
} else if (row === 0) {
down = true // 如果触碰到第一行,转向下
}
}
return arr.join('') // 直接拼接数组返回就行了
};
第二种思路
我们观察一下第一行的所有值和最后一行的所有值,发现一个规律,
(1,7,13)(4, 10) 都是按 6 递增,行数有 4 行 + z 的向上方向会经过除了第一行和最后一行的所有行,所以 6 的获取来源为 numRows + (numRows - 2), 按照数学方法可以简化为 numRows * 2 - 2 按照上面的规律遍历所有字母,展开会变成
这时候我们可以发现,第[0]行和第[numRows-1] 行已经是最终的结果了,也就是目标的最上最下两行已经完成了
其他行则不完整分为了两个部分,第[numRows-1 - 1]行,也就是倒数第二行+第[numsRows-1 + 1]行,也就是溢出的第一行逐位按照顺序拼接在一起就是最终需求的结果,其它行同上
于是统计规律,当 i % n < numRows的时候,按照图中也就是前面 4 行的,直接放进数组存起来就可以了,也就是arr[i % n] += s[i]
但是当 i % n >= numRows的时候,也就是 2 图中蓝色的线的部分我们需要围绕最后一行做个翻转,再放到数组中,也就是 最后一行的索引 - (当前溢出的行应该在的索引 - 最后一行的索引) , numRows - 1 - (i % n - (numRows - 1)),按照图 1 第一行数字 5为例 , 3 - (4 - 3) = 2, 6 为例 3 - (5 - 3) = 1, 7 为例, 6 % 6 < 6,直接走 4 的逻辑 优化6 的公式 numRows - 1 - (i % n - (numRows - 1)) = numRows - 1 - i % n + (numRows - 1) = numRows - 1 - i % n + numRows - 1 = numRows + numRows - 1 - 1 - i%n = numRows * 2 - 2 - i % n
使用三元优化if判断,简化为i % n < numRows ? arr[i % n] += s[i] : arr[numRows * 2 - 2 - i % n] += s[i]
拼接返回就可以了
代码实现
var convert = function (s, numRows) {
if (numRows === 1) return s // 首先还是,只有一行直接返回
let arr = new Array(numRows).fill('') // 创建一个数组,存储每行
let n = numRows * 2 - 2 // 1.
for (let i = 0; i < s.length; i++) {
i % n < numRows ? arr[i % n] += s[i] : arr[numRows * 2 - 2 - i % n] += s[i] // 8.
}
return arr.join('') // 拼接返回
};
总结
实现方式其实有很多,这里仅供参考~
由于刚开始刷题,也不知道从哪里刷好,如果前辈们有好的建议,希望不吝赐教,感谢🌹