一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
题目
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3 输出:"PAHNAPLSIIGYIR"
示例 2: 输入:s = "PAYPALISHIRING", numRows = 4 输出:"PINALSIGYAHRPI" 解释:
示例 3:
输入:s = "A", numRows = 1 输出:"A"
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/zi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析
-
到达底端后,是从底端往上读
-
分组,记录字符串,最后按行顺序拼接起来就行,斜边上的值对组取余填入适当的位置
-
具体的行数不重要,保证先后顺序就行,
['abc','def']
,'abc'在第0行,最后join起来结果是一样的 -
以
numRows
为组的话,数学关系繁琐,如numRows=3
,端点下标为:0,2,4,6...,要考虑偏移、取余、顶底端
思路
以2*numRows-2(即一列+斜列,斜列去掉两端端点,底端已经加上了,顶端不需要)
为一组,这样的话,由于下标从0开始,顶点的余数会正好为0;
底点取余则为numRows-1
斜边上的点要放入的行数则正好为组长度2*numRows-2
减 余数,其实就是当前字符到组末尾的距离
不懂的话凑合看这张图:
然后用一个数组表示行字符串,下标index
对应行,在遍历字符串的过程中,将对应行数的字符放入数组第index
行累加就可以了,结合分析3,第0行也是可以的,不必刻意从第1行开始,最后将行与行之间拼接起来就可以了;
代码实现
/**
* @param {string} s
* @param {number} numRows
* @return {string}
*/
var convert = function(s, numRows) {
if(numRows<=1) return s;
const ans = new Array(numRows+1).fill(''); // 用来存放结果数组
for(let i = 0;i<s.length;i++){
let groupCnt = 2*numRows-2 // 分组长度
let remainer = i%groupCnt; // 取余,在直边上,行数即为余数
if(remainer > numRows-1){ // 余数大于numRows-1,说明在斜边上
remainer = groupCnt - remainer; // 斜边字母的行数为分组数减余数
}
ans[remainer]+=s[i] // 每行的字符累加就行,行读取就是这个顺序
}
return ans.join("") // 行与行之间拼接起来
};
比起用numRows来分组应该是更简单的;