Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述
- 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
- 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下图:
- 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
- 请你实现这个将字符串进行指定行数变换的函数:
- string convert(string s, int numRows);
二、思路分析:
- 给定一个字符串和行数,其实是按照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;
};
四、总结:
- 这个解法的时间和空间度教高,但是我只能想到这个了。肯定还有其他更容易的方法,可以去看看大佬写的题解。