算法系列--Spiral Matrix
来源:互联网 发布:大庆油田网络客服电话 编辑:程序博客网 时间:2024/06/05 04:14
继续看一个与数组操作相关的算法,这道题目给我们提供了一个遍历二维数组的新方式——螺旋式遍历。
问题描述
原文:
Given a matrix of m × n elements ( m rows, n columns), return all elements of the matrix in spiral order.
For example, Given the following matrix:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
You should return [1,2,3,6,9,8,7,4,5]
大意:给一个m x n(m行,n列)的矩阵,返回矩阵所有元素的螺旋访问序列。
思路分析
题目给我们提供了一个的新的角度来遍历二维数组,通常情况下我们会以行优先或者列优先的方式进行数组的遍历。螺旋式遍历的方式从数组的外层开始,层层深入,直到所有元素被访问到。要想实现这种遍历方式,最直观和容易想到的就是模拟法,模拟你手动写出遍历序列的过程。而关键点在于如何实现这种访问方式,显然我们仍要依赖循环的方式,仔细分析可以发现,遍历的过程可以分为四个步骤,从矩阵左上到右上,从右上到右下,从右下到左下,从左下到左上,然后依次向内层递进,循环往复。程序中我们可以设置4个循环来依次描述这4个方向上的遍历过程,现在的关键问题就是如何控制循环中游标的起始位置和终止位置。可以明确指导,当一个方向上的遍历完成后,下次再沿同一方向遍历时,起始元素和终止元素都要都要向中心收缩一位,我们可以设置4个变量beginX,endX,beginY,endY,分别描述X(水平方向)和Y(垂直方向)游标的范围变化特征。以下,我们给出实际的代码。
/** 螺旋方式访问二维数组,返回结果集合*/public static List<Integer> spiralOrder(int[][] matrix) { List<Integer> result = new ArrayList<Integer>(); int m = matrix.length; int n = matrix[0].length; int beginX, endX, beginY, endY; beginX = 0; endX = n - 1; beginY = 0; endY = m - 1; while (true) { // 从左上到右上 for (int j = beginX; j <= endX; j++) { result.add(matrix[beginY][j]); } beginY++; if (beginY > endY) break; // 从右上到右下 for (int i = beginY; i <= endY; i++) { result.add(matrix[i][endX]); } endX--; if (endX < beginX) break; // 从右下到左下 for (int j = endX; j >= beginX; j--) { result.add(matrix[endY][j]); } endY--; if (endY < beginY) break; // 从左下到左上 for (int i = endY; i >= beginY; i--) { result.add(matrix[i][beginX]); } beginX++; if (beginX > endX) break; } return result;}
说明:以上算法时间复杂度为O(n²).注意循环的终止条件,当任意方向上的游标出现本末倒置的情况,即起始游标值大于终结游标的条件下,说明遍历已完成,程序应该跳出循环,返回最终遍历的集合。
问题变形
原文
Given an integer n, generate a square matrix filled with elements from 1 to n² in spiral order.
For example, Given n = 3,
You should return the following matrix:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
大意:给一个整型数n,生成一个n * n方阵,并按照螺旋的遍历方式,从1到n²填充这个方阵。
分析
这道题目是上一个题目的变形,有了上一个题目的基础,我们只需修改for循环内部的操作就行了,给出以下代码。
public static int[][] generateMatrix2(int n) { int[][] result = new int[n][n]; int num, beginX, endX, beginY, endY; num = 1; beginX = 0; endX = n - 1; beginY = 0; endY = n - 1; while (true) { // 从左上到右上 for (int j = beginX; j <= endX; j++) { result[beginX][j] = num++; } beginY++; if (beginY > endY) break; // 从右上到右下 for (int i = beginY; i <= endY; i++) { result[i][endX] = num++; } endX--; if (endX < beginX) break; // 从右下到左下 for (int j = endX; j >= beginX; j--) { result[endY][j] = num++; } endY--; if (endY < beginY) break; // 从左下到左上 for (int i = endY; i >= beginY; i--) { result[i][beginX] = num++; } beginX++; if (beginX > endX) break; } return result; }
说明:算法时间复杂度仍然为O(n²)。但是有一点小问题,可以知道,变形后的问题中m * n常规矩阵变成了n * n的方阵,但是我们仍然利用了4个变量,可其中有两个变量其实重复的,我们能不能稍作改进呢?我们直接给出只用两个游标变量的遍历方法。
/* * 按照螺旋式生成数组,返回生成后的二维数组 */public static int[][] generateMatrix1(int n) { int[][] result = new int[n][n]; if (n <= 0) return null; int begin = 0, end = n - 1; int num = 1; while (begin < end) { // 从左到右 for (int j = begin; j < end; j++) { result[begin][j] = num++; System.out.print("[" + begin + "," + j + "] "); } System.out.println(); // 从上到下 for (int i = begin; i < end; i++) { result[i][end] = num++; System.out.print("[" + i + "," + end + "] "); } System.out.println(); // 从右到左 for (int j = end; j > begin; j--) { result[end][j] = num++; System.out.print("[" + end + "," + j + "] "); } System.out.println(); // 从下到上 for (int i = end; i > begin; i--) { result[i][begin] = num++; System.out.print("[" + i + "," + begin + "] "); } System.out.println(); begin++; end--; } if (begin == end) { result[begin][end] = num; System.out.print("[" + begin + "," + end + "] "); } return result;}
说明:此种写法类似和之前的方法类似,无非是将游标变量的增减操作操作放在了循环的末尾统一进行,改进了while(条件)中的条件,并将最后一个元素的遍历放在循环之外。并没有提高程序效率,所以读者只需要掌握一种方法即可。
- 算法系列--Spiral Matrix
- 算法系列——Spiral Matrix
- 算法系列——Spiral Matrix II
- leetcode系列(62)Spiral Matrix, Spiral Matrix II
- [leetcode刷题系列]Spiral Matrix
- [leetcode刷题系列]Spiral Matrix II
- leetcode系列(3)Spiral Matrix II
- Leetcode算法学习日志-54 Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- Spiral Matrix
- SAS hash 树与多维临时数组的比较
- 【转载】python基础一(加了我的注…
- android:descendantfocusability
- 【转载】Python 基础语法(二)…
- logistic 回归
- 算法系列--Spiral Matrix
- mapreduce算中位数
- Python教程:[63]操作目录/路径【2…
- R主页上的图的代码
- hive array、map、stru…
- 误操作寄存器位引发的hardfault
- 随机森林 VS Grad…
- Hive几种数据导出方式
- Python 中的 property 属性