Leetcode——螺旋矩阵1,2

1. 螺旋矩阵1

在这里插入图片描述

(1)按圈模拟

(用的叶姐图)——记录觉得特别好的题解
在这里插入图片描述

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        //特判为空情况,防止出问题
        if (matrix == null || m == 0 || n == 0) 
            return new int[0];
        List<Integer> ans = new ArrayList<>();
        circle(matrix, 0, 0, m -1, n - 1, ans);
        return ans;
    }

    // 遍历 以 (x1, y1) 作为左上角,(x2, y2) 作为右下角形成的「圈」
    public void circle(int[][] matrix, int x1, int y1, int x2, int y2, List<Integer> ans) {
        if (x2 < x1 || y2 < y1)
            return;
        
        // 只有一行时,按「行」遍历, 注意这里要遍历到最后一位 i <= y2, matrix[x1][i]
        if (x1 == x2) {
            for (int i = y1; i <= y2; i++) {
                ans.add(matrix[x1][i]);
            }
            return;
        }

        // 只有一列时,按「列」遍历,同理 i <= x2, matrix[i][y2]
        if (y1 == y2) {
            for (int i = x1; i <= x2; i++) {
                ans.add(matrix[i][y2]);
            }
            return;
        }

        // 遍历当前 圈
        for (int i = y1; i < y2; i++) {
            ans.add(matrix[x1][i]);
        }

        for (int i = x1; i < x2; i++) {
            ans.add(matrix[i][y2]);
        }

        for (int i = y2; i > y1; i--) {
            ans.add(matrix[x2][i]);
        }

        for (int i = x2; i > x1; i--) {
            ans.add(matrix[i][y1]);
        }

        // 往里收一圈,继续遍历
        circle(matrix, x1 + 1, y1 + 1, x2 - 1, y2 - 1, ans);
    }
}

(2)按层模拟

在这里插入图片描述

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> list = new ArrayList<Integer>();
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0)
            return list;
        int m = matrix.length;
        int n = matrix[0].length;
        int i = 0;

        //统计矩阵从外向内的层数,如果矩阵非空,那么它的层数至少为1层
        int count = (Math.min(m, n)+1)/2;

        //从外部向内部遍历,逐层打印数据
        while (i < count) {
            for (int j = i; j < n-i; j++) {
				list.add(matrix[i][j]);
			}

            for (int j = i+1; j < m-i; j++) {
				list.add(matrix[j][(n-1)-i]);
			}

            for (int j = (n-1)-(i+1); j >= i && (m-1-i != i); j--) {
				list.add(matrix[(m-1)-i][j]);
			}

            for (int j = (m-1)-(i+1); j >= i+1 && (n-1-i) != i; j--) {
				list.add(matrix[j][i]);
			}
        	i++;
        }
        return list;
    }

}

(3)直接遍历矩阵

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {

        List<Integer> ans = new ArrayList<>();
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0)
            return ans;
            
        // 左列,右列,上行,下行
        int left = 0;
        int right = matrix[0].length-1;
        int top = 0;
        int down = matrix.length-1;
        
        while (true) {
             //左 -> 右
             for (int i = left; i <= right; ++i) {
                 ans.add(matrix[top][i]);
             }
             top++;
             if (top > down) 
                break;
            
            //右上 -> 右下
             for (int i = top; i <= down; ++i) {
                 ans.add(matrix[i][right]);
             }
             right--;
             if (left > right) 
                break;

            //右 -> 左
             for (int i = right; i >= left; --i) {
                 ans.add(matrix[down][i]);
             }
             down--;
             if (top > down) 
                break;

            //左下 -> 左上
             for (int i = down; i >= top; --i) {
                 ans.add(matrix[i][left]);
             }
             left++;
             if (left > right) 
                break;
             
        }
        return ans;
    }
}

2. 螺旋矩阵2

在这里插入图片描述

(1)按圈模拟

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] ans = new int[n][n];
        circle(0, 0, n - 1, n - 1, 1, ans);
        return ans;
    }
    void circle(int x1, int y1, int x2, int y2, int start, int[][] ans) {
        if (x2 < x1 || y2 < y1) return ;

        
        if (x1 == x2) {
            ans[x1][y1] = start;
            return;
        }

        if (y1 == y2) {
            ans[x1][y1] = start;
            return;
        }

        int val = start;        //从1开始

        // 从左往右,
        for (int i = y1; i < y2; i++) 
            ans[x1][i] = val++;

        // 从右往下
        for (int i = x1; i < x2; i++) 
            ans[i][y2] = val++;

        // 从右往左
        for (int i = y2; i > y1; i--) 
            ans[x2][i] = val++;

        //从下往上
        for (int i = x2; i > x1; i--) 
            ans[i][y1] = val++;

        circle(x1 + 1, y1 + 1, x2 - 1, y2 - 1, val, ans); 
    }
}

(2)按照方向模拟

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] ans = new int[n][n];
        
        // 左列,右列,上行,下行
        int left = 0;
        int right = n-1;
        int top = 0;
        int down = n-1;

        int val = 1;
        while (true) {
             //左 -> 右
             for (int i = left; i <= right; ++i) {
                 ans[top][i] = val++;
             }
             top++;
             if (top > down) 
                break;
            
            //右上 -> 右下
             for (int i = top; i <= down; ++i) {
                 ans[i][right] = val++;
             }
             right--;
             if (left > right) 
                break;

            //右 -> 左
             for (int i = right; i >= left; --i) {
                 ans[down][i] = val++;
             }
             down--;
             if (top > down) 
                break;

            //左下 -> 左上
             for (int i = down; i >= top; --i) {
                 ans[i][left] = val++;
             }
             left++;
             if (left > right) 
                break;
        }
        return ans;
    }
    
}

化简一下更好看:

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] ans = new int[n][n];

        // 定义四个方向
        int[][] dirs = new int[][]{{0,1},{1,0},{0,-1},{-1,0}};

        for (int x = 0, y = 0, d = 0, i = 1; i <= n * n; i++) {
            ans[x][y] = i;

            // 下一步要到达的位置
            int nexX = x + dirs[d][0];
            int nexY = y + dirs[d][1];
            
            // 如果下一步发生「溢出」或者已经访问过(说明四个方向已经走过一次)
            if (nexX < 0 || nexX >= n || nexY < 0 || nexY >= n || ans[nexX][nexY] != 0) {
                d = (d + 1) % 4;
                nexX = x + dirs[d][0];
                nexY = y + dirs[d][1];
            }

            x = nexX;
            y = nexY;
        }
        return ans;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yawn__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值