Spiral Matrix
Given a matrix of m x 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].

Solution 1:

使用递归,一次扫描一整圈,然后用x,y记录这个圈的左上角,递归完了都+1。rows, cols记录还没扫的有多少。思想比较简单,但相当容易出错。起码提交了5次才最后过。

注意:1. 扫描第一行跟最后一行要扫到底部为止,而扫描左列和右列只需要扫中间的。

1  2  3   4

5  6  7   8

9 10 11 12

例如以上例子: 你要 先扫1234, 然后是8,然后是12 11 10 9 然后是 5.

不能这样:123, 4 8, 12 11 10 , 9 5。 用后者的方法在只有一个数字 1的时候 就完全不会扫到它。

 public List<Integer> spiralOrder1(int[][] matrix) {
List<Integer> ret = new ArrayList<Integer>();
if (matrix == null || matrix.length == 0
|| matrix[0].length == 0) {
return ret;
} rec(matrix, 0, 0, matrix.length, matrix[0].length, ret); return ret;
} public static void rec(int[][] matrix, int x, int y, int rows, int cols, List<Integer> ret) {
if (rows <= 0 || cols <= 0) {
return;
} // first line
for (int i = 0; i < cols; i++) {
ret.add(matrix[x][y + i]);
} // right column
for (int i = 1; i < rows - 1; i++) {
ret.add(matrix[x + i][y + cols - 1]);
} // down row
if (rows > 1) {
for (int i = cols - 1; i >= 0; i--) {
ret.add(matrix[x + rows - 1][y + i]);
}
} // left column. GO UP.
if (cols > 1) {
for (int i = rows - 2; i > 0; i--) {
ret.add(matrix[x + i][y]);
}
} rec (matrix, x + 1, y + 1, rows - 2, cols - 2, ret);
}

Solution 2:

http://blog.csdn.net/fightforyourdream/article/details/16876107?reload

感谢以上文章作者提供的思路,我们可以用x1,y1记录左上角,x2,y2记录右下角,这样子我们算各种边界值会方便好多。也不容易出错。

 /*
Solution 2:
REF: http://blog.csdn.net/fightforyourdream/article/details/16876107?reload
此算法比较不容易算错
*/
public List<Integer> spiralOrder2(int[][] matrix) {
List<Integer> ret = new ArrayList<Integer>();
if (matrix == null || matrix.length == 0
|| matrix[0].length == 0) {
return ret;
} int x1 = 0;
int y1 = 0; int rows = matrix.length;
int cols = matrix[0].length; while (rows >= 1 && cols >= 1) {
// Record the right down corner of the matrix.
int x2 = x1 + rows - 1;
int y2 = y1 + cols - 1; // go through the WHOLE first line.
for (int i = y1; i <= y2; i++) {
ret.add(matrix[x1][i]);
} // go through the right column.
for (int i = x1 + 1; i < x2; i++) {
ret.add(matrix[i][y2]);
} // go through the WHOLE last row.
if (rows > 1) {
for (int i = y2; i >= y1; i--) {
ret.add(matrix[x2][i]);
}
} // the left column.
if (cols > 1) {
for (int i = x2 - 1; i > x1; i--) {
ret.add(matrix[i][y1]);
}
} // in one loop we deal with 2 rows and 2 cols.
rows -= 2;
cols -= 2;
x1++;
y1++;
} return ret;
}

Solution 3:

http://fisherlei.blogspot.com/2013/01/leetcode-spiral-matrix.html

感谢水中的鱼大神。这是一种相当巧妙的思路,我们这次可以用Iterator来实现了,记录2个方向数组,分别表示在x方向,y方向的前进方向。1表示右或是下,-1表示左或是向上,0表示不动作。

// 1: means we are visiting the row by the right direction.
// -1: means we are visiting the row by the left direction.
int[] x = {1, 0, -1, 0};
        
// 1: means we are visiting the colum by the down direction.
// -1: means we are visiting the colum by the up direction.
int[] y = {0, 1, 0, -1};

这种方向矩阵将会很常用在各种旋转数组上。

 /*
Solution 3:
使用方向矩阵来求解
*/ public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> ret = new ArrayList<Integer>();
if (matrix == null || matrix.length == 0
|| matrix[0].length == 0) {
return ret;
} int rows = matrix.length;
int cols = matrix[0].length; int visitedRows = 0;
int visitedCols = 0; // indicate the direction of x // 1: means we are visiting the row by the right direction.
// -1: means we are visiting the row by the left direction.
int[] x = {1, 0, -1, 0}; // 1: means we are visiting the colum by the down direction.
// -1: means we are visiting the colum by the up direction.
int[] y = {0, 1, 0, -1}; // 0: right, 1: down, 2: left, 3: up.
int direct = 0; int startx = 0;
int starty = 0; int candidateNum = 0;
int step = 0;
while (true) {
if (x[direct] == 0) {
// visit Y axis.
candidateNum = rows - visitedRows;
} else {
// visit X axis
candidateNum = cols - visitedCols;
} if (candidateNum <= 0) {
break;
} ret.add(matrix[startx][starty]);
step++; if (step == candidateNum) {
step = 0;
visitedRows += x[direct] == 0 ? 0: 1;
visitedCols += y[direct] == 0 ? 0: 1; // move forward the direction.
direct ++;
direct = direct%4;
} // 根据方向来移动横坐标和纵坐标。
startx += y[direct];
starty += x[direct];
} return ret;
}

SOLUTION 4 (December 2nd 更新):

对solution 2改进了一下,使用top,bottom,right,left记录四个角。程序更简洁漂亮。

 public class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> ret = new ArrayList<Integer>();
if (matrix == null ||matrix.length == 0) {
// 注意在非法的时候,应该返回空解,而不是一个NULL值
return ret;
} // Record how many rows and cols we still have.
int rows = matrix.length;
int cols = matrix[0].length; // The four coners.
int top = 0;
int left = 0;
int bottom = rows - 1;
int right = cols - 1; // every time we go through two rows and two cols.
for (; rows > 0 && cols > 0; rows -= 2, cols -= 2, top++, left++, bottom--, right--) {
// the first line.
for (int i = left; i <= right; i++) {
ret.add(matrix[top][i]);
} // the right column.
for (int i = top + 1; i < bottom; i++) {
ret.add(matrix[i][right]);
} // the down line;
if (rows > 1) {
for (int j = right; j >= left; j--) {
ret.add(matrix[bottom][j]);
}
} // the left column.
if (cols > 1) {
for (int i = bottom - 1; i > top; i --) {
ret.add(matrix[i][left]);
}
}
} return ret;
}
}

2015.1.9 redo:

可以不用rows/cols来记录行列数。只需要判断四个边界是否相撞即可。

 public List<Integer> spiralOrder3(int[][] matrix) {
List<Integer> ret = new ArrayList<Integer>();
if (matrix == null || matrix.length == || matrix[].length == ) {
return ret;
} int rows = matrix.length;
int cols = matrix[].length; int left = ;
int right = cols - ;
int top = ;
int bottom = rows - ; while (left <= right && top <= bottom) {
// line top.
for (int i = left; i <= right; i++) {
ret.add(matrix[top][i]);
} // line right;
for (int i = top + ; i <= bottom - ; i++) {
ret.add(matrix[i][right]);
} // line bottom.
if (top != bottom) {
for (int i = right; i >= left; i--) {
ret.add(matrix[bottom][i]);
}
} // line left;
if (left != right) {
for (int i = bottom - ; i >= top + ; i--) {
ret.add(matrix[i][left]);
}
} left++;
right--;
top++;
bottom--;
} return ret;
}

GitHub CODE:

spiralOrder.java

LeetCode: Spiral Matrix 解题报告的更多相关文章

  1. 【LeetCode】54. Spiral Matrix 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 维护四个边界和运动方向 保存已经走过的位置 日期 题 ...

  2. LeetCode: Spiral Matrix II 解题报告-三种方法解决旋转矩阵问题

    Spiral Matrix IIGiven an integer n, generate a square matrix filled with elements from 1 to n2 in sp ...

  3. 【LeetCode】01 Matrix 解题报告

    [LeetCode]01 Matrix 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/01-matrix/#/descripti ...

  4. 【LeetCode】378. Kth Smallest Element in a Sorted Matrix 解题报告(Python)

    [LeetCode]378. Kth Smallest Element in a Sorted Matrix 解题报告(Python) 标签: LeetCode 题目地址:https://leetco ...

  5. LeetCode: Combination Sum 解题报告

    Combination Sum Combination Sum Total Accepted: 25850 Total Submissions: 96391 My Submissions Questi ...

  6. [LeetCode] Spiral Matrix II 螺旋矩阵之二

    Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For ...

  7. [LeetCode] Spiral Matrix 螺旋矩阵

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  8. 【LeetCode】Permutations 解题报告

    全排列问题.经常使用的排列生成算法有序数法.字典序法.换位法(Johnson(Johnson-Trotter).轮转法以及Shift cursor cursor* (Gao & Wang)法. ...

  9. LeetCode - Course Schedule 解题报告

    以前从来没有写过解题报告,只是看到大肥羊河delta写过不少.最近想把写博客的节奏给带起来,所以就挑一个比较容易的题目练练手. 原题链接 https://leetcode.com/problems/c ...

随机推荐

  1. vs2013没有代码提法的一种解决办法

    把这两个勾去掉,然后关掉vs再打开,最后重新勾选上就行了.

  2. 〖Linux〗gvim使用alt+1,2,3..进行标签页切换

    gvim ~/.gvimrc,往里边添加: """"""""""""" ...

  3. 【Python】学习笔记六:循环

    循环是一个结构,导致一个程序要重复一定的次数 条件循环也一样,当条件变为假,循环结束 For循环 在python for循环遍历序列,如一个列表或一个字符. for循环语法:   ——for iter ...

  4. aop注解 事例

    spring.xml中aop的配置 <!-- aop的配置 --> <aop:config> <!-- 切入点表达式 --> <aop:pointcut ex ...

  5. JS阻止冒泡方法(转)

    S事件流其中一种是冒泡事件,当一个元素被触发一个事件时,该目标元素的事件会优先被执行,然后向外传播到每个祖先元素,恰如水里的一个泡泡似的,从产生就一直往上浮,到在水平面时,它才消失.在这个过程中,如果 ...

  6. [Python]项目打包:5步将py文件打包成exe文件(转)

    1.下载pyinstaller并解压(可以去官网下载最新版): http://nchc.dl.sourceforge.net/project/pyinstaller/2.0/pyinstaller-2 ...

  7. 从使用 KVO 监听 readonly 属性说起

    01.KVO 原理 KVO 是 key-value observing 的简写,它的原理大致是: 1.当一个 object(对象) 有观察者时候,动态创建这个 object(对象) 的类的子类(以 N ...

  8. 【Linux】撷取命令grep

    什么是撷取命令啊?说穿了,就是将一段数据经过分析后,取出我们所想要的.或者是经由分析关键词,取得我们所想要的那一行! 不过,要注意的是,一般来说,撷取信息通常是针对『一行一行』来分析的, 并不是整篇信 ...

  9. ps减去图层混合模式

    ps减去图层混合模式 CMYK 1.1.青色作为基色,品红作为混合色(减去混合模式) 红反即青色(绿色+蓝色) - 绿反即品红色(红色+蓝色)= 绿色   公式简化: 绿色 + 蓝色 - 红色 - 蓝 ...

  10. 限制 nuget 更新包的版本号

    今天在搜索其它问题的时候,突然发现一个使用 nuget 的小技巧. 因为浏览器兼容性的问题,很多网站项目引用的 jQuery 组件版本需要保持在 2.0 以下,因为 2.0 以上需要现代浏览器的支持, ...