leetcode 6: Z 字形变换(js)

142 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

题目

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

image.png

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);  

示例 1:

输入:s = "PAYPALISHIRING", numRows = 3 输出:"PAHNAPLSIIGYIR"

示例 2: 输入:s = "PAYPALISHIRING", numRows = 4 输出:"PINALSIGYAHRPI" 解释:

image.png

示例 3:

输入:s = "A", numRows = 1 输出:"A"

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/zi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析

  1. 到达底端后,是从底端往上读

  2. 分组,记录字符串,最后按行顺序拼接起来就行,斜边上的值对组取余填入适当的位置

  3. 具体的行数不重要,保证先后顺序就行,['abc','def'],'abc'在第0行,最后join起来结果是一样的

  4. numRows为组的话,数学关系繁琐,如numRows=3,端点下标为:0,2,4,6...,要考虑偏移、取余、顶底端

思路

2*numRows-2(即一列+斜列,斜列去掉两端端点,底端已经加上了,顶端不需要)为一组,这样的话,由于下标从0开始,顶点的余数会正好为0;

底点取余则为numRows-1

斜边上的点要放入的行数则正好为组长度2*numRows-2 减 余数,其实就是当前字符到组末尾的距离

不懂的话凑合看这张图:

image.png

然后用一个数组表示行字符串,下标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来分组应该是更简单的;

结果

image.png