这篇文章介绍几种花式遍历二维数组的技巧,废话少说,直接上题目!!
详情可见题目 旋转图像
今天 (2022-04-08 20:36:26) 看到这个题目的时候,突然想起来了自己在很久很久前写了一丢丢小小的技巧总结,贴出链接 link
哈哈哈哈哈哈,居然还看到有一个外国人评论我了,今日份开心!!!!
看了上面贴出来的总结,相信就很明了了。就是一种很常规的思路。唯一的弊端就是,需要分析清楚移动元素的「下标关系」,绕来绕去的,很容易搞错!
今天学习了一种全新的思路,好家伙,直接 OMG,惊呆了!!
这里先上一个引例
对于字符串I am a good boy,如何原地反转所有单词的顺序,反转后的结果应该为boy good a am I
相信很多人的惯性思维就是,先根据「空格」切分字符串,然后把「首尾元素」交换
这里提供一种新的思路
yob doog a ma Iboy good a ma I
好了,针对今天的题目,我们的思路「先沿 左上-右下 的对角线翻转,然后对每一行进行反转」,如下图所示:
这个题目是顺时针,如果是逆时针,也只需要稍作变化即可,如下图所示:
是不是有种发现新大陆的感觉,哈哈哈哈哈
下面是题目的详细代码 (顺时针)
public void rotate(int[][] matrix) { int n = matrix.length; // 沿对角线翻转 for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { int tmp = matrix[i][j]; matrix[i][j] = matrix[j][i]; matrix[j][i] = tmp; } } // 对每行反转 for (int i = 0; i < n; i++) { for (int j = 0; j < n / 2; j++) { int tmp = matrix[i][j]; matrix[i][j] = matrix[i][n - j - 1]; matrix[i][n - j - 1] = tmp; } }}详情可见题目 螺旋矩阵
这个题目其实没有什么技巧可言,就是模拟螺旋移动的过程
需要注意的是,边界的控制,以及下标的变化。请详细看代码中的注释,写的很清楚了,同时结合下面的图
xpublic List<Integer> spiralOrder(int[][] matrix) { int m = matrix.length; int n = matrix[0].length; int upper_bound = 0, lower_bound = m - 1; int left_bound = 0, right_bound = n - 1; List<Integer> res = new ArrayList<>(); while (res.size() < m * n) { // 从左到右 // 「上边界」要在「下边界」上面 if (upper_bound <= lower_bound) { // 从「左边界」开始,到「右边界」截止 for (int j = left_bound; j <= right_bound; j++) { res.add(matrix[upper_bound][j]); } // 「上边界」下移 upper_bound++; }
// 从上到下 // 「右边界」要在「左边界」右边 if (right_bound >= left_bound) { // 从「上边界」开始,到「下边界」截止 for (int i = upper_bound; i <= lower_bound; i++) { res.add(matrix[i][right_bound]); } // 「右边界」左移 right_bound--; }
// 从右到左 // 「下边界」要在「上边界」下面 if (lower_bound >= upper_bound) { // 从「右边界」开始,到「左边界」截止 for (int j = right_bound; j >= left_bound; j--) { res.add(matrix[lower_bound][j]); } // 「下边界」上移 lower_bound--; }
// 从下到上 // 「左边界」要在「右边界」左边 if (left_bound <= right_bound) { // 从「下边界」开始,到「上边界」截止 for (int i = lower_bound; i >= upper_bound; i--) { res.add(matrix[i][left_bound]); } // 「左边界」右移 left_bound++; } } return res;}详情可见题目 螺旋矩阵 II
这个题目就是上面题目的逆过程,把代码稍微修改一下即可
xxxxxxxxxxpublic int[][] generateMatrix(int n) { int upper_bound = 0, lower_bound = n - 1; int left_bound = 0, right_bound = n - 1; int[][] matrix = new int[n][n]; int count = 0; while (count < n * n) { // 从左到右 // 「上边界」要在「下边界」上面 if (upper_bound <= lower_bound) { // 从「左边界」开始,到「右边界」截止 for (int j = left_bound; j <= right_bound; j++) { matrix[upper_bound][j] = ++count; } // 「上边界」下移 upper_bound++; }
// 从上到下 // 「右边界」要在「左边界」右边 if (right_bound >= left_bound) { // 从「上边界」开始,到「下边界」截止 for (int i = upper_bound; i <= lower_bound; i++) { matrix[i][right_bound] = ++count; } // 「右边界」左移 right_bound--; }
// 从右到左 // 「下边界」要在「上边界」下面 if (lower_bound >= upper_bound) { // 从「右边界」开始,到「左边界」截止 for (int j = right_bound; j >= left_bound; j--) { matrix[lower_bound][j] = ++count; } // 「下边界」上移 lower_bound--; }
// 从下到上 // 「左边界」要在「右边界」左边 if (left_bound <= right_bound) { // 从「下边界」开始,到「上边界」截止 for (int i = lower_bound; i >= upper_bound; i--) { matrix[i][left_bound] = ++count; } // 「左边界」右移 left_bound++; } } return matrix;}