转载自:http://blog.csdn.net/ylyg050518/article/details/48547619

继续看一个与数组操作相关的算法,这道题目给我们提供了一个遍历二维数组的新方式——螺旋式遍历。


问题描述

原文:

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(条件)中的条件,并将最后一个元素的遍历放在循环之外。

这两种遍历方法的本质差别,在于遍历的数目划分不同罢了。如:int[] a={1,2,3,4,5,6,7,8,9} 该方法第一次遍历1,2;上面的方法遍历1,2,3;

Demo下载

java算法之简单的矩阵螺旋式遍历Spiral Matrix相关推荐

  1. C#LeetCode刷题之#59-螺旋矩阵 II(Spiral Matrix II)

    目录 问题 示例 分析 问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3678 访问. 给定一个正整数 n,生成一 ...

  2. java算法:冒泡排序

    java算法:冒泡排序 冒泡排序:不断遍历文件,交换倒序的相邻元素,直到文件排好顺序.冒泡排序的主要优点是容易实现,冒泡排序通常会比选择排序.插入排序慢. 如,对EXAMPLE 字母进行排序:  E  ...

  3. java算法的实际应用,工程中的算法应用 - 简单的三个例子

    [TOC] 前言 其实这篇文章早就想写了,因为自己太懒,到现在才更新.虽然这三个例子都是最简单的算法,但是不得不说,相比较暴力的做法,确实提升了效率,也节省了程序员的时间.三个例子中用到的分别是二分查 ...

  4. 蚁群算法java实现_简单蚁群算法 + JAVA实现蚁群算法

    一 引言 蚁群算法(ant colony optimization,ACO),又称蚂蚁算法,是一种用来在图中寻找优化路径的机率型技术.它由Marco Dorigo于1992年在他的博士论文中引入,其灵 ...

  5. 小球碰壁反弹加分_用Java实现小球碰壁反弹的简单实例(算法十分简单)

    用Java实现小球碰壁反弹的简单实例(算法十分简单) 核心代码如下: if(addX){ x+=3; }else{ x-=3; } if(addY){ y+=6; }else{ y-=6; } if( ...

  6. java实现约瑟夫环完整算法_Java简单实现约瑟夫环算法示例

    Java简单实现约瑟夫环算法示例 发布时间:2020-10-01 14:19:56 来源:脚本之家 阅读:104 作者:perfect亮 本文实例讲述了Java简单实现约瑟夫环算法.分享给大家供大家参 ...

  7. 惊!面试现场,简单几道java算法题,90%程序员没写出来

    近几个月很多大学实习生离校找实习工作去了,本以为自己很值钱,实际上发现自己并不值钱,想象着自己能赚很多钱了,结果只能拿到一点微薄的工资,很多人会怪公司给的少,但是你有没有想过,你自己的技术值多少钱?你 ...

  8. JAVA 两个简单的抽奖算法

    不多说了,代码不多,算法也简单 方法一: /*** 获取中奖号的算法,方法会在每次抽到一个中奖号后,将最后一个号码填充到此位置,实现不重复抽取.* <p>* 经过多次测试,此方法在大数据时 ...

  9. 悲哀!面试现场,简单几道java算法题,90%程序员没写出来

    这两天小编逛论坛的时候发现一个很有意思的事情,就是一位互联网公司的面试官分享的,他们最近想招一批java的实习生,所以他们的面试题并不难,但是前来面试的人,却很多都挂在了几道算法题上,要么就是逻辑不严 ...

最新文章

  1. python模块引用
  2. 微软向马斯克的人工智能项目OpenAI投资10亿美元
  3. 矩阵快速幂及斐波那契数列模板
  4. tomcat配置多站点
  5. 3.Java 面试题整理(线程篇)
  6. 对于asp.net服务器推送和客户端拉拽技术知识讲述
  7. 使用tcl文件分配管脚
  8. EasyUI DataGrid 添加排序
  9. VC++中视频采集系统(摄像头的制作,串口通信的应用)
  10. 购物车html js代码,js实现购物车功能
  11. 基于Ymodem协议的IAP上位机(C#)
  12. pythoneducoder苹果梨子煮水的功效_梨子煮水真的有润肺止咳化痰的功效吗?
  13. JAVA8 日期和时间(LocalDate、LocalDateTime、ZoneId、Duration、Period、Instant)API 用法详解
  14. qt绘画事件-设置背景图片
  15. 2017-07-06:大神
  16. uniapp引用外部js_Uniapp怎么引入外部js
  17. OSChina 周五乱弹 —— 但愿老死电脑间,不愿鞠躬老板前
  18. Unity 给手游用的高性能辉光(Bloom) Shader
  19. 三国杀online网页版服务器更新,2019年《三国杀Online》更迭汇总,一切为了“fun”...
  20. hibernate 报错大全

热门文章

  1. 计算机管理服务游戏,Win10全新任务管理器上线:专为PC游戏优化
  2. 车载FAKRA 高清倒车影像连接线束
  3. 递归函数内部的原理????不要跟我讲自己调用自己这样的话,我一分也不给你的zz
  4. 武汉体育学院计算机设计大赛,首届“经管杯”创业设计大赛顺利落幕
  5. 计算机辅助CAD试题,计算机辅助技术CAD考试试题.doc
  6. 从Android 6.0源码的角度剖析View的绘制原理
  7. 【Swift 60秒】80 - Classes: Summary
  8. 【工具】超好用的windows搜索工具Listary
  9. 将其出版的所有PDF版图书对所有读者免费开放下载
  10. Vue项目优化,减小打包体积