携手创作,共同成长!这是我参与「掘金日新计划 · 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
}
总结
- 按照题意进行模拟的方法是最容易想到的,稍微想一下是可以对矩阵空间压缩,找规律的方法最快,也相对来说不是很容易想到的方法
- 今天也是有收获的一天