一起刷LeetCode——Z字形变换(模拟)

84 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

Z字形变换

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

分析

  • 可以通过描述直接模拟这种行为,可以使用二维矩阵来模拟

二维矩阵模拟

  • 遍历字符串,字符在矩阵中是按列排列成Z字形,没有排的矩阵项是空字符串,之后遍历二维矩阵,得到的字符串就是答案

代码

var convert = function(s, numRows) {
    if (numRows === 1 || s.length < numRows) return s;
    let rows = []
    let converted = '';
    let reverse = false;
    let count = 0
    for (let i = 0; i < numRows; i++) {
        rows[i] = [];
    }
    for (let i = 0; i < s.length; i++) {
        rows[count].push(s[i]);
        reverse ? count-- : count++;
        if (count === numRows - 1 || count === 0) reverse = !reverse;
    }
    return rows.reduce((converted, cur) => converted + cur.join(''), '');
}

矩阵优化

  • 如果忽略Z这个形状,想象这个矩阵从两边向中间压,把空余的空间压缩掉,可以得出一个结论:字符串从上到下,然后从下到上,接着从上到下,如此循环往复把字符放到矩阵中,这样在维护答案的时候,一维数组就可以

代码

var convert = function(s, numRows) {
    let matrix = new Array(numRows).fill("");
    let idx = 0;
    while (idx < s.length) {
        for (let i = 0; i < numRows; i++) {
            if (idx >= s.length) break;
            matrix[i] += s[idx];
            idx++;
        }
        for (let i = numRows-2; i > 0; i--) {
            if (idx >= s.length) break;
            matrix[i] += s[idx];
            idx++;
        }       
    }
    return matrix.join("");
};

寻找规律

  • 通过对比每一行的字符下标总结规律,按照Z字形变换之后的每一行的字符串下标的差值相加是相等的,与numRows相关,这些相邻下标差值的和等于numRows*2-2,因此可以通过遍历字符串直接得出每一行的字符串,把每行的字符连起来就是答案

代码

var convert = function(s, numRows) {
    if (numRows === 1) return s
    let result = ""
    let period = numRows * 2 - 2
    let diff1 = period, diff2 = 0
        for (let i = 0; i < numRows; i++) {
        let currStrIdx = i
        let useFirst = true
	while (currStrIdx < s.length) {
	  useFirst = diff2 === 0 ? true : diff1 === 0 ? false : useFirst
          useFirst ? currStrIdx += diff1 : currStrIdx += diff2
          useFirst = !useFirst
        }
    diff1 -= 2
    diff2 += 2
  }
  return result
}

总结

  • 按照题意进行模拟的方法是最容易想到的,稍微想一下是可以对矩阵空间压缩,找规律的方法最快,也相对来说不是很容易想到的方法
  • 今天也是有收获的一天