Z 字形变换

191 阅读2分钟

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

一、题目描述

  • 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
  • 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下图:
  • 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
  • 请你实现这个将字符串进行指定行数变换的函数:
  • string convert(string s, int numRows); image.png

二、思路分析:

  • 给定一个字符串和行数,其实是按照N字排列的,不知道这个题目的Z字怎么来的。先想到的就是将字符串切割成数组,然后将数组按照一定的方式去截取
  • 这里首先将字符串数组复制了一份,splice方法会改变原数组的长度,所以要先复制一份。
  • 然后根据传入的numRows确定截取的周期,numRows为3时,第一次截取3个字符,第二次截取一个,第三次又是三个,所以周期是2
  • 后面需要根据字符位置来拼接字符串,所以我创建了一个二维数组来保存按顺序截取的字符串。示例2排列方式可以写成
 let res = [['P', 'A', 'Y', P], [null,null, 'A', null], [null, 'L', null, null],['I', 'S', 'H', 'I'], [null, null, 'R', null], [null, 'I', null, null], ['N', 'G', null, null]]
  • 所以要做的就是要把给定的字符串转化成上面的格式,然后将每个字数组的第一项拼接,再每个数组的第二项拼接,以此类推

注意的地方

  • 因为是用的new Array(num),所以拼接的时候要先判断 resultArr[j][i] 是否存在。
  • 当给的字符串长度小于等于2时,不管numRows为多少,直接返回原来的字符串就好
  • 当给定的numRows为1时,就不需要排列,直接返回

三、AC 代码:

function convert(s: string, numRows: number): string {
    if(s.length <=2 || numRows === 1) return s;
    let arr = s.split('');
    let copyArr = JSON.parse(JSON.stringify(arr));
    let resultArr = []
    for(let i = 0; i < arr.length; i++){
        if(copyArr.length > 0){
            for(let j = 0; j < numRows - 1; j++){
                if(j===0){
                    resultArr.push(copyArr.splice(0, numRows))
                } else {
                    let splArr = new Array(numRows);
                    splArr[numRows - j - 1] = copyArr.splice(0, 1)[0]
                    resultArr.push(splArr)
                }
            }
        } else {
            break
        }
    }
    let str = ''
    for(let i = 0; i < numRows; i++){
        for(let j = 0; j < resultArr.length; j++){
            if(resultArr[j][i]){
                str = str + resultArr[j][i]
            }
        }
    }
    return str;
};

四、总结:

  • 这个解法的时间和空间度教高,但是我只能想到这个了。肯定还有其他更容易的方法,可以去看看大佬写的题解。

image.png