leetcode刷题记录-6. Z 字形变换

164 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

前言

今日的题目为中等,最简单的方法就是用一个二维数组去模拟平面,知道了移动的过程之后,用数组来进行模拟就可以很容易的解题

每日一题

今天的每日一题 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);  

示例 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

题解

利用二维数组直接模拟

分析移动过程

题目需要我们将一个字符串按照 ‘z’ 字排列,所以我们可以用一个二维数组来模拟平面,直接在上面进行平移,通过题目给的第一个例子和第二个例子,我们可以来分析一下应该要怎么移动:

image.png

由两个例子应该能看出我们就是按照一个 ‘z’ 字来进行移动,一开始的时候会向下移动,在移动 numRows-1 位的时候换为向右上移动,在移动 numRows-1 之后又换位向下移动,一直重复,知道遍历完全部的字符串。

创建模拟过程的二维数组

那么再有了上面的基础上,我们就只需要去创建两个空数组,数组的长度和宽度偷懒的话可以直接生成和字符串长度相同的,就一定能满足要求。

不过写题就要考虑一下内存问题,从上面的图可以看出来,我们生成的二维数组的大小,数组的高就一定是和 numRows 一样,数组的宽就可以通过计算得出。

由上面的移动过程,我们可以看出来其实移动是重复的,每一次重复次数为 re,向下移动 numRows-1 在 向右上移动 numRows-1 为一个循环,所以我们能得到一次循环 re 为 numRows*2 -2。并且每一次循环会占用的宽度为 r−1。

然后知道了总的字符串长度,又知道了每一次需要的宽度和使用的字符串的长度,我们就能够得出一个趋近于最小需要的宽度:

 const w = Math.floor((s.length + re - 1) / re) * (numRows - 1);

利用二维数组模拟过程

有了数组之后,我们初始化点的位置在 (0,0) 从这里开始模拟移动的过程,并且把移动过的位置更新值为当前遍历到的字符。

模拟完成之后,再次便利字符串并且把有值得位置拼接起来,就是题目需要的答案。

代码

/**
 * @param {string} s
 * @param {number} numRows
 * @return {string}
 */
 var convert = function(s, numRows) {
    if (numRows === 1 || numRows >= s.length) {
        return s;
    }
    const re = numRows * 2 - 2;
    const w = Math.floor((s.length + re - 1) / re) * (numRows - 1);
    const arr = new Array(numRows).fill(0).map(() => new Array(w).fill(0));
    for (let i = 0, x = 0, y = 0; i < s.length; i++) {
        arr[x][y] = s[i];
        if (i % re < numRows - 1) {
            x++; 
        } else {
            x--;
            y++; 
        }
    }
    const ans = [];
    for (const row of arr) {
        for (const ch of row) {
            if (ch !== 0) {
                ans.push(ch);
            }
        }
    }
    return ans.join('');
};

image.png