力扣题目2624. 蜗牛排序
语言TypeScript
如内容有不对的地方,恳请指出
提示:以下是本篇文章正文内容,下面案例可供参考
请你编写一段代码为所有数组实现 snail(rowsCount,colsCount) 方法,该方法将 1D 数组转换为以蜗牛排序的模式的 2D 数组。无效的输入值应该输出一个空数组。当 rowsCount * colsCount !==nums.length 时。这个输入被认为是无效的。
蜗牛排序从左上角的单元格开始,从当前数组的第一个值开始。然后,它从上到下遍历第一列,接着移动到右边的下一列,并从下到上遍历它。将这种模式持续下去,每列交替变换遍历方向,直到覆盖整个数组。例如,当给定输入数组 [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15] ,当 rowsCount = 5 且 colsCount = 4 时,需要输出矩阵如下图所示。注意,矩阵沿箭头方向对应于原数组中数字的顺序
示例 1:
输入:
nums = [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15]
rowsCount = 5
colsCount = 4
输出:
[
[19,17,16,15],
[10,1,14,4],
[3,2,12,20],
[7,5,18,11],
[9,8,6,13]
]
示例 2:
输入:
nums = [1,2,3,4]
rowsCount = 1
colsCount = 4
输出:[[1, 2, 3, 4]]
示例 3:
输入:
nums = [1,3]
rowsCount = 2
colsCount = 2
输出:[]
Explanation: 2 * 2 = 4, 且原数组 [1,3] 的长度为 2; 所以,输入是无效的。
提示:
0 <= nums.length <= 250
1 <= nums[i] <= 1000
1 <= rowsCount <= 250
1 <= colsCount <= 250
declare global {
interface Array<T> {
snail(rowsCount: number, colsCount: number): number[][];
}
}
Array.prototype.snail = function(rowsCount: number, colsCount: number): number[][] {
if (this.length !== rowsCount * colsCount) {
return [];
}
const res: number[][] = [];
for (let i = 0; i < rowsCount; i++) {
res.push([]);
}
let seq: boolean = true; // 正向还是逆向
let start: number = 0;
for (let i = 0; i < this.length; i++) {
res[start].push(this[i]);
if (seq) {
if (start === rowsCount - 1) {
seq = false;
} else {
start++;
}
} else {
if (start === 0) {
seq = true;
} else {
start--;
}
}
}
return res;
}
declare global {
interface Array<T> {
snail(rowsCount: number, colsCount: number): number[][];
}
}
这段代码声明了一个名为 snail 的方法,它被添加到了 Array 接口的原型上。Array
中的T 在 TypeScript 中用作泛型类型参数,用于表示一种类型,在实际使用时会被具体的类型替代。这样做的效果是,所有的数组实例都可以调用这个 snail 方法。而declare global 用于声明全局变量、全局类型或全局方法,使得这个接口就可以在代码的任何地方被访问和使用,而不需要额外的导入或声明。
Array.prototype.snail = function(rowsCount: number, colsCount: number): number[][]
这行代码通过 Array.prototype.snail
,我们将 snail 方法添加到了数组原型(Array 对象的原型)上。有空针对prototype原型对象写一篇文章,这里暂不展开,关注博主防止错过。这意味着,一旦定义了这个方法,所有的数组实例都可以调用这个方法,就好像它是数组自身的方法一样。
snail方法的返回值number[][]表示一个二维数组,其中的每个元素也是一个数组,并且这些子数组的元素都是数字类型。举个例子:
const grid: number[][] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
根据题目
输入:
nums = [1,3]
rowsCount = 2
colsCount = 2
输出:[]
Explanation: 2 * 2 = 4, 且原数组 [1,3] 的长度为 2; 所以,输入是无效的。
写出以下代码:
if (this.length !== rowsCount * colsCount) {
return [];
}
检查传入的一维数组 this 是否包含足够的元素来填充指定的行数 rowsCount 和列数 colsCount 的二维数组。如果一维数组的长度不满足指定的行数和列数要求,那么返回一个空数组 [],表示无效的输入。
const res: number[][] = [];
声明一个名为res的空的二维数组
观察题目给出的例子,有多少行(rowsCount)在二维数组里面就有多少个元素(每个元素是一个数组)
示例 1:
输入:
nums = [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15]
rowsCount = 5
colsCount = 4
输出:
[
[19,17,16,15],
[10,1,14,4],
[3,2,12,20],
[7,5,18,11],
[9,8,6,13]
]
所以我们写出下面代码:
for (let i = 0; i < rowsCount; i++) {
res.push([]);
}
这样做的目的是往二维数组res中添加和行数(rowsCount)相等数量的空数组。如果rowsCount = 5:
res = [
[], // 第一行
[], // 第二行
[], // 第三行
[], // 第四行
[] // 第五行
];
let seq: boolean = true; // 正向还是逆向
let start: number = 0;
声明两个变量,seq用来判断箭头方向,而start用于判断往二维数组中哪一行添加数字。
for (let i = 0; i < this.length; i++) {
res[start].push(this[i]);
if (seq) {
if (start === rowsCount - 1) {
seq = false;
} else {
start++;
}
} else {
if (start === 0) {
seq = true;
} else {
start--;
}
}
}
解析这段代码,在第一遍循环中,start的值是0,也代表指向第1行,这时候seq是true也就是向下的,于是我们进入以下代码块:
if (start === rowsCount - 1) {
seq = false;
} else {
start++;
}
这段代码的含义是,如果start不是最后一行,就继续让start沿着seq的方向走一格,直到走到最后一行,这时候seq = false
改变方向,这时候方向变成向上。根据题目给的图,在第四遍循环的时候,start++
后值变成4,在第五遍循环的时候 i的值是4,由res[4].push(this[4])
将9添加到第五行(start = 4是第五行)。start不再往下走,这时候顺序改变成向上,在第六遍循环的开始,这时候i已经由4变成了5,由res[4].push(this[5])
将8添加到第五行(start = 4是第五行),也就是第五行中的前两个元素9和8是这样来的。
[9,8,6,13] //第五行
else {
if (start === 0) {
seq = true;
} else {
start--;
}
}
至于剩下的代码和上面意思一样,只不过seq的方向变后,start自然不是++而是- -。
return res;
当给定的一维数组所有元素遍历完后,将返回填充好的二维数组res。