04 矩阵(二维数组)特殊遍历相关题目


螺旋矩阵

54. 螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
image.png
解题思想:
image.png
每一轮螺旋遍历都要重复的走上述四条边,因此只需要在循环内部控制四条边的起始点即可。
循环内部是对四条边的顺序遍历。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        int len1=matrix.length;
        int len2=matrix[0].length;

        int l=0,r=len2-1;
        int t=0,b=len1-1;

        List<Integer> res=new ArrayList<Integer>();

        while(true){
            //第一条线:从左到右横
            for(int j=l;j<=r;j++){
                res.add(matrix[t][j]);
            }
            t++;
            if(t>b)    break;

            //第二线:从上到下右
            for(int i=t;i<=b;i++){
                res.add(matrix[i][r]);
            }
            r--;
            if(r<l)    break;

            //第三条线:从右到左横
            for(int j=r;j>=l;j--){
                res.add(matrix[b][j]);
            }
            b--;
            if(b<t)    break;

            //第四条线:从下到上左
            for(int i=b;i>=t;i--){
                res.add(matrix[i][l]);
            }
            l++;
            if(l>r)    break;
        }
        return res;
    }
}

59. 螺旋矩阵 II

题目描述:
给你一个正整数 n ,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

解题思想0:

直接参考上一题,自定义一个n*n的矩阵,然后对矩阵进行螺旋遍历赋值即可。

class Solution {
    public int[][] generateMatrix(int n) {
        //最直接的思想:直接定义一个n*n的数组然后对其进行螺旋赋值
        int[][] res=new int[n][n];
        int x=1;
        int l=0,r=n-1,t=0,b=n-1;

        //开始进行螺旋遍历
        while(true){
            for(int j=l;j<=r;j++){
                res[t][j]=x++;
            }
            t++;
            if(t>b) break;

            for(int i=t;i<=b;i++){
                res[i][r]=x++;
            }
            r--;
            if(r<l) break;

            for(int j=r;j>=l;j--){
                res[b][j]=x++;
            }
            b--;
            if(b<t) break;

            for(int i=b;i>=t;i--){
                res[i][l]=x++;
            }
            l++;
            if(l>r) break;
        }
        return res;
    }
}

解题思想1:

(代码随想录思想)
以圈数为循环条件,
在循环中进行每一圈数据的填充:
从左到右
从上到下
从右到左
从下到上
设置四个边界变量left,right,top,bottom控制填充的范围,
注意在填充时,控制每条边填充的范围,此处设置填充范围为左闭右开,即[left,right)范围。
一圈数据填充完毕后,要移动四个边界,并且进行loop++,进入下一圈填充。
注意:循环结束后,如果n是奇数,最中间的一个元素会没有填充到,因此在最后要进行判断。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 代码随想录思想
        int left=0,right=n-1,top=0,bottom=n-1;
        int loops=n/2,loop=1;
        int mid=n/2;
        int num=1;
        vector<vector<int>> matrix(n, vector<int>(n, 0));
        int i=0,j=0;

        //按照圈数进行循环
        while(loop<=loops){
            //每圈的填充:遵循左闭右开原则:例如从左到右填充时,仅填充这些元素[left,right)
            //1.从左到右
            for(i=top,j=left;j<right;j++){
                matrix[i][j]=num++;
            }
            //2.从上到下
            for(i=top,j=right;i<bottom;i++){
                matrix[i][j]=num++;
            }
            //3.从右到左
            for(i=bottom,j=right;j>left;j--){
                matrix[i][j]=num++;
            }
            //4.从下到上
            for(i=bottom,j=left;i>top;i--){
                matrix[i][j]=num++;
            }
            //一圈元素填充完毕后,将圈的四个边界收缩,然后loop++,进入下一圈的填充
            right--;
            top++; 
            bottom--;
            left++;
            loop++;
        }

        if(n%2!=0){
            matrix[mid][mid]=n*n;
        }
        return matrix;
    }
};

解题思想2:☆

思想参考:
https://leetcode.cn/problems/spiral-matrix-ii/solution/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/
image.png
以填充元素为循环:

class Solution(object):
    def generateMatrix(self,n):
        """
        :type n: int
        :rtype: List[List[int]]
        """
        
        left, right, bottom, top = 0, n - 1, n - 1, 0
        i, j = 0, 0
        res = [[0] * n for _ in range(n)]
        num=1

        while num<=n**2:
            for j in range(left,right+1):
                res[i][j]=num
                num+=1
            top+=1
            for i in range(top,bottom+1):
                res[i][j]=num
                num+=1
            right-=1
            for j in range(right,left-1,-1):
                res[i][j]=num
                num+=1
            bottom-=1
            for i in range(bottom,top-1,-1):
                res[i][j]=num
                num+=1
            left+=1
        return res

有序二维数组中元素的查找

题目描述:
在一个二维数组中,每一行数据都是按照从左到右递增的顺序;
每一列数据都是从上到下递增。
实现一个函数,输入一个这样的二维数组,以及一个整数,要求判断该数是否存在于该数组中。
例:
1 2 8 9
2 4 9 12
4 7 10 13
6 8 11 15

解题思想:
一般拿到一个数组,第一反应都是从数组的左上角开始对数据进行处理;
但其实从这个题目分析,给定一个数字,从矩阵的左上角开始搜索,如果大于当前值,那么后续待查找的位置仅剔除了当前位置,因为当前位置其右侧以及下方的值都是大于该元素的。
换一个角度,从数组的右上角开始搜索:

  • 如果大于当前值,那么可以剔除掉当前行的所有元素,从其下方的行继续查找;
  • 如果小于当前元素,那么可以剔除当前列,从其右方的列继续查找。
bool find(vector<vector<int>> nums,int target){
    int row=nums.size();
    int col=nums[0].size();
    
    int x=0,y=col-1;
    while(x<row&& y>=0){
        if(nums[x][y]==target)	return true;
        else if(nums[x][y]<target)	row++;
        else col--;
    }
    return false;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值