使用 JS 输出螺旋矩阵
关于螺旋矩阵
这是我曾经遇到过的面试题,在 LeetCode 上找到了题目的原型,难度中等。题目描述如下:
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]
解题思路
[[1, 1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 2, 2, 1],
[1, 2, 3, 3, 3, 2, 1],
[1, 2, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 1, 1]]
这是一道难度中等的题目,但是第一次看到题目时还是有一些困惑,不过仔细分析后很容易找到思路。比较直观的思路是逐层法,从外向内循环每一层。其中单层循环的方法也有很多,我使用了插入法循环每一层。以下是 4X4 矩阵循环的步骤:
/**
* --------------------------------------------
* 以 4X4 矩阵为例
*
* [[ 1, 2, 3, 4],
* [ 5, 6, 7, 8],
* [ 9,10,11,12],
* [13,14,15,16]]
*
* --------------------------------------------
* 循环第一层
*
* [[ 1, 2, 3, 4], | 1
* [ 5, 8], | 2
* [ 9, 12], | 3
* [13,14,15,16]] ▼ 4
*
* --------------------------------------------
* 将元素按顺序插入数组,`|` 表示插入位置
*
* [ 1, 2, 3, 4, |]
* (8, 5)┘
*
* [ 1, 2, 3, 4, 8, |, 5]
* (12, 9)┘
*
* [ 1, 2, 3, 4, 8, 12, |, 9, 5]
* (16, 15, 14, 13)┘
*
* [ 1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5]
*
* 第一层循环结束
*
*/
通过以上步骤拆分,可以看到输出螺旋矩阵还是比较容易的,以下是具体的 JS 代码。
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function(matrix) {
// 最终返回的结果数组
var ans = [];
var spiralLoop = function() {
// 临时数组
var arr = [];
for (var i = 0; i < matrix.length; i++) {
if (i === 0) {
arr = arr.concat(matrix[0]);
}
if (i > 0 && i < matrix.length - 1) {
var insertRight = matrix[0].length === 1 ?
[] :
arr.splice(-(i - 1), i - 1), // 插入位置右侧的元素
last = matrix[i].splice(-1, 1), // 数组尾元素
first = matrix[i].splice(0, 1); // 数组首元素
// 在指定位置插入元素
arr = arr.concat(last, first, insertRight);
}
if (matrix.length > 1 && i === matrix.length - 1) {
var insertRight = matrix[0].length === 1 ?
[] :
arr.splice(-(matrix.length - 2), matrix.length - 2);
// 将最后一行倒叙排列然后插入指定位置
arr = arr.concat(matrix[matrix.length - 1].reverse(), insertRight);
}
}
// 删除矩阵的首尾行,得到的就是下一次需要遍历的矩阵
matrix.splice(0, 1);
matrix.splice(-1, 1);
ans = ans.concat(arr);
// 根据矩阵内是否还存在数组进行递归
if (matrix.length >= 1) {
spiralLoop(matrix);
}
}
spiralLoop(matrix);
return ans;
};
以上程序的运行时间大约在 60 ms 左右,超过所有提交答案的五成,中规中矩吧,距离最优算法还有一定差距。
官方答案
LeetCode 原站给出了这道题的解题思路及代码,中文站则没有。官方介绍了两种方法,一种是模拟法,另一种是逐层法,其中逐层法的思路和我的思路是相同的,不过单层循环的方法不同。对于二维矩阵的题目,我最先想到的也是模拟法,也就是模拟行走路线及方向,但是因为判断条件有点复杂而放弃了。具体实现可以看官网文章 https://leetcode.com/articles/spiral-matrix/,以下是两种方法的 python 实现,因时间关系,我就不写 JS 版本了,后续有时间再补上,感兴趣的博友可以自己转换。
1、模拟法
class Solution(object):
def spiralOrder(self, matrix):
if not matrix: return []
R, C = len(matrix), len(matrix[0])
seen = [[False] * C for _ in matrix]
ans = []
dr = [0, 1, 0, -1]
dc = [1, 0, -1, 0]
r = c = di = 0
for _ in range(R * C):
ans.append(matrix[r][c])
seen[r][c] = True
cr, cc = r + dr[di], c + dc[di]
if 0 <= cr < R and 0 <= cc < C and not seen[cr][cc]:
r, c = cr, cc
else:
di = (di + 1) % 4
r, c = r + dr[di], c + dc[di]
return ans
2、逐层法
class Solution(object):
def spiralOrder(self, matrix):
def spiral_coords(r1, c1, r2, c2):
for c in range(c1, c2 + 1):
yield r1, c
for r in range(r1 + 1, r2 + 1):
yield r, c2
if r1 < r2 and c1 < c2:
for c in range(c2 - 1, c1, -1):
yield r2, c
for r in range(r2, r1, -1):
yield r, c1
if not matrix: return []
ans = []
r1, r2 = 0, len(matrix) - 1
c1, c2 = 0, len(matrix[0]) - 1
while r1 <= r2 and c1 <= c2:
for r, c in spiral_coords(r1, c1, r2, c2):
ans.append(matrix[r][c])
r1 += 1; r2 -= 1
c1 += 1; c2 -= 1
return ans
使用 JS 输出螺旋矩阵的更多相关文章
- 关于输出螺旋矩阵的demo
输出类似 1 2 3 8 9 4 7 6 5 主要难点是如何找到表示的算法 我的理解是,先生成一个n*n的矩阵,然后再往里面塞数字,而塞的方法分别有四种:由左往右,由上往下,由右往左,由下往上,没塞完 ...
- PAT 1050. 螺旋矩阵(25)
本题要求将给定的N个正整数按非递增的顺序,填入"螺旋矩阵".所谓"螺旋矩阵",是指从左上角第1个格子开始,按顺时针螺旋方向填充.要求矩阵的规模为m行n列,满足条 ...
- PAT-乙级-1050. 螺旋矩阵(25)
1050. 螺旋矩阵(25) 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 本题要求将给定的N个正整数按非递增的 ...
- PAT 1050 螺旋矩阵(25)(代码)
1050 螺旋矩阵(25)(25 分) 本题要求将给定的N个正整数按非递增的顺序,填入"螺旋矩阵".所谓"螺旋矩阵",是指从左上角第1个格子开始,按顺时针螺旋方 ...
- PAT B1050 螺旋矩阵 (25 分)
本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”.所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充.要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N:m ...
- 1050. 螺旋矩阵(25) pat乙级题
本题要求将给定的N个正整数按非递增的顺序,填入“螺旋矩阵”.所谓“螺旋矩阵”,是指从左上角第1个格子开始,按顺时针螺旋方向填充.要求矩阵的规模为m行n列,满足条件:m*n等于N:m>=n:且m- ...
- PAT——1050. 螺旋矩阵
本题要求将给定的N个正整数按非递增的顺序,填入“螺旋矩阵”.所谓“螺旋矩阵”,是指从左上角第1个格子开始,按顺时针螺旋方向填充.要求矩阵的规模为m行n列,满足条件:m*n等于N:m>=n:且m- ...
- 【算法笔记】B1050 螺旋矩阵
1050 螺旋矩阵 (25 分) 本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”.所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充.要求矩阵的规模为 m 行 ...
- PAT 1050 螺旋矩阵
https://pintia.cn/problem-sets/994805260223102976/problems/994805275146436608 本题要求将给定的 N 个正整数按非递增的顺序 ...
随机推荐
- js设置回车键触发事件
设置按回车键时触发查询事件: document.onkeydown = function(e){ var ev = document.all ? window.event : e; if(ev.key ...
- Java数据结构和算法 - 链表
Q: 为什么要引入链表的概念?它是解决什么问题的? A: 数组作为数据存储结构有一定的缺陷,在无序数组中,搜索是低效的:而在有序数组中,插入效率又很低:不管在哪一个数组中删除效率都很低:况且一个数组创 ...
- 解决 Mac launchpad 启动台 Gitter 图标无法删除的问题
Mac 删除应用非常简单,将应用拖到回收站就删除了.或者进入应用程序文件夹,选中程序,command + delete 就删除了应用,这也是删除文件的快捷键. 但是,安装 Gitter 后,删除了应用 ...
- Android or Java的回调粗俗理解 这才是最通俗易懂的
FUCK,网上装逼者甚众矣! 网上一堆关于JAVA函数回调的见解文章,都说自己写的明白,但没几个我看的明白的. 不如自己写一个东西,回头自己看着舒服 回调函数:定义自己百度 干嘛的? 场景就是事务A执 ...
- 【Spark篇】---SparkSql之UDF函数和UDAF函数
一.前述 SparkSql中自定义函数包括UDF和UDAF UDF:一进一出 UDAF:多进一出 (联想Sum函数) 二.UDF函数 UDF:用户自定义函数,user defined functio ...
- Linux命令(精简版)
1:init 0 关机(root用户可用) 2:exit退出终端 3:who查看登录用户 4:whoami 查看当前用户 5:data 查看当前时间 data “月日时分年” 修改当前 ...
- 『练手』004 Laura.SqlForever如何扩展 导航栏 工具栏 右键菜单 插件
004 Laura.SqlForever如何扩展 导航栏 工具栏 右键菜单 插件 导航栏 插件扩展 比如下图的 窗口 > 关闭所有文档 这个导航栏: 在 任何程序集,任何命名空间,任 ...
- unity中ScriptableObject在assetbundle中的加载
转载请标明出处:http://www.cnblogs.com/zblade/ 以前都是写一些个人的调研博客,从今天开始,也写一些个人在开发中遇到的一些可以分享的趟坑博客,为后续的开发人员提供一些绵薄之 ...
- 学习ASP.NET Core Razor 编程系列十八——并发解决方案
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- 使用JsonProperty Attribute修改返回json
使用JsonProperty Attribute修改返回 json 值的name 本例使用JsonPropertyAttribute在序列化为JSON时更改属性的名称. public class Vi ...