Z 字形变换

65 阅读2分钟

题目:

将一个给定字符串 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"

题解

方法一

  • 解题思路:

    遍历字符串,将字符一一填入每一行,我们用数组arr记录每一行已经填入的数据 以s = "PAYPALISHIRING", numRows = 3为列:

步骤1. 第1次循环,第1个字符填入第1行;   i = 0; arr[0] = 'P'
步骤2. 第2次循环,第2个字符填入第2行;   i = 1; arr[1] = 'A'
步骤3. 第3次循环,第3个字符填入第3行   i = 2; arr[2] = 'Y' (第numRows次)
步骤4. 第4次循环,第4个字符填入第2行   i = 3; arr[1] = 'AP'
步骤5. 第5次循环,第5个字符填入第2行   i = 4; arr[0] = 'PA'
......

以arr下标代表行数,用rows表示;arr[rows]为每行的排的字符串,不难发现
当rows = 0时,开始从上往下依次填写,rows递增;如上述步骤1、步骤2、步骤3 当rows = numRows - 1时,开始翻转,从下往上依次填写,rows递减;如上述步骤3、步骤4、步骤5

  • 代码实现:
/**
 * @param {string} s
 * @param {number} numRows
 * @return {string}
 */
var convert = function(s, numRows) {
    const n = s.length;
    if (numRows === 1 || numRows >= n) {
        return s;
    }
    var arr = new Array(numRows).fill('')
    var rows = 0, // 当前字符应该填写到第几行
        flag = -1; // 往上还是往下 
    for (var i = 0; i < n; i++) {
        arr[rows] += s.charAt(i);
        // 每次等于0(第一次循环)或者numRows - 1(第numRows循环)都会反转
        if (rows === 0 || rows === numRows - 1) {
            flag = - flag;
        }
        rows += flag;
    }
    return arr.join('');
};
  • 复杂度分析:

    • 时间复杂度 O(n) :遍历一遍字符串 s
    • 空间复杂度 O(n) :各行字符串共占用O(n)额外空间。