首页 > 其他分享 >力扣第五十九题——螺旋矩阵II

力扣第五十九题——螺旋矩阵II

时间:2024-08-15 21:55:05浏览次数:14  
标签:II 边界 填充 int 第五十九 矩阵 力扣 num mat

内容介绍

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

示例 1:

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

示例 2:

输入:n = 1
输出:[[1]]

提示:

  • 1 <= n <= 20

完整代码

 class Solution {
    public int[][] generateMatrix(int n) {
        int l = 0, r = n - 1, t = 0, b = n - 1;
        int[][] mat = new int[n][n];
        int num = 1, tar = n * n;
        while(num <= tar){
            for(int i = l; i <= r; i++) mat[t][i] = num++; // left to right.
            t++;
            for(int i = t; i <= b; i++) mat[i][r] = num++; // top to bottom.
            r--;
            for(int i = r; i >= l; i--) mat[b][i] = num++; // right to left.
            b--;
            for(int i = b; i >= t; i--) mat[i][l] = num++; // bottom to top.
            l++;
        }
        return mat;
    }
}

思路详解

代码功能

这段代码定义了一个名为Solution的类,其中包含一个名为generateMatrix的方法。该方法用于生成一个按顺时针顺序填充的n阶矩阵,矩阵中的元素从1开始递增,直到n*n。

思路详解

  1. 初始化边界变量

    • lr分别表示矩阵的左边界和右边界,初始值分别为0和n-1。
    • tb分别表示矩阵的顶部边界和底部边界,初始值分别为0和n-1。
  2. 创建矩阵

    • 使用new int[n][n]创建一个n阶矩阵mat,用于存储填充的元素。
  3. 初始化填充变量

    • num表示当前要填充的数字,初始值为1。
    • tar表示填充的目标值,即n*n。
  4. 循环填充矩阵

    • 使用while循环,当num小于等于tar时,继续填充矩阵。
  5. 按顺时针顺序填充矩阵

    • 从左到右填充顶部行:使用for循环,从左边界l到右边界r,填充顶部行mat[t][i],并将num递增。
    • 从上到下填充右侧列:使用for循环,从顶部边界t到底部边界b,填充右侧列mat[i][r],并将num递增。
    • 从右到左填充底部行:使用for循环,从右边界r到左边界l,填充底部行mat[b][i],并将num递增。
    • 从下到上填充左侧列:使用for循环,从底部边界b到顶部边界t,填充左侧列mat[i][l],并将num递增。
  6. 更新边界

    • 在每完成一轮填充后,更新边界变量:顶部边界t向下移动一位(t++),右边界r向左移动一位(r--),底部边界b向上移动一位(b--),左边界l向右移动一位(l++)。
  7. 返回填充后的矩阵

    • num大于tar时,循环结束,返回填充好的矩阵mat

总结

这段代码通过不断缩小矩阵的边界,并在每轮循环中按照顺时针顺序填充矩阵,最终生成一个按顺时针顺序递增的n阶矩阵。整个算法的时间复杂度为O(n^2),空间复杂度为O(n^2),适用于需要生成螺旋矩阵的场景

知识点精炼

 

 矩阵初始化
  • 使用int[n][n]声明并初始化一个二维数组,用于存储螺旋矩阵的元素。
2. 边界控制
  • 使用四个变量l(左边界)、r(右边界)、t(上边界)、b(下边界)来控制矩阵的填充范围。
3. 循环填充
  • 使用while循环,条件为当前填充数字num小于等于矩阵元素总数tar(即n*n)。
4. 顺时针填充顺序
  • 顶部行:从左到右填充,更新上边界t
  • 右侧列:从上到下填充,更新右边界r
  • 底部行:从右到左填充,更新下边界b
  • 左侧列:从下到上填充,更新左边界l
5. 边界收缩
  • 在每轮填充后,相应地调整边界变量的值,以缩小下一次填充的范围。
6. 返回结果
  • 当填充完毕,返回填充好的二维数组mat
7. 算法效率
  • 时间复杂度:O(n^2),因为每个元素都需要填充一次。
  • 空间复杂度:O(n^2),用于存储矩阵的二维数组。
8. 编程技巧
  • 使用嵌套for循环实现矩阵的顺时针填充。
  • 通过边界变量的调整,简化循环逻辑,避免复杂的条件判断。 

扩展:如何避免填充重复数字 

在给出的代码中,填充重复数字通常是由于边界调整不当导致的。为了确保每个数字只填充一次,需要仔细管理边界变量的更新。以下是避免填充重复数字的几个关键点:

  1. 更新边界前检查:在每轮填充完成后,确保在更新边界之前,新边界不会与旧边界重叠。

  2. 避免边界重叠:在每次循环结束时,更新边界之前,应该检查是否已经到达了矩阵的极限边界,以避免重叠。

以下是修改后的代码,其中包含了避免填充重复数字的逻辑:

class Solution {
    public int[][] generateMatrix(int n) {
        int l = 0, r = n - 1, t = 0, b = n - 1;
        int[][] mat = new int[n][n];
        int num = 1, tar = n * n;
        while(num <= tar){
            // 从左到右填充顶部行
            for(int i = l; i <= r; i++) mat[t][i] = num++;
            t++; // 更新上边界

            // 从上到下填充右侧列
            for(int i = t; i <= b; i++) mat[i][r] = num++;
            r--; // 更新右边界

            // 确保底部行未被填充
            if(t <= b) {
                // 从右到左填充底部行
                for(int i = r; i >= l; i--) mat[b][i] = num++;
                b--; // 更新下边界
            }

            // 确保左侧列未被填充
            if(l <= r) {
                // 从下到上填充左侧列
                for(int i = b; i >= t; i--) mat[i][l] = num++;
                l++; // 更新左边界
            }
        }
        return mat;
    }
}

在上述代码中,我添加了两个if语句来检查在填充底部行和左侧列之前,新的上边界t是否已经超过了下边界b,以及新的左边界l是否已经超过了右边界r。这样可以确保在矩阵的最后一行和最后一列时不会重复填充。

通过这种方式,我们可以确保每个数字只被填充一次,避免了任何可能的重复填充问题。

 

标签:II,边界,填充,int,第五十九,矩阵,力扣,num,mat
From: https://blog.csdn.net/m0_74932528/article/details/141232686

相关文章

  • UCOSIII信号量详解
    目录​编辑前言一、信号量的类型二、信号量的使用方法2.1创建信号量2.2请求信号量:2.3释放信号量:三、信号量的作用四、注意事项五、信号量的API函数六、代码实现6.1创建信号量6.2使用信号量前言UCOSIII信号量是UCOSIII操作系统中用于任务同步和互斥访问共......
  • LeetCode40.组合总和II
    LeetCode40.组合总和II力扣题目链接(opensnewwindow)给定一个数组candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合。candidates中的每个数字在每个组合中只能使用一次。说明:所有数字(包括目标数)都是正整数。解集不能包含重复的组合。......
  • 【食用指南】Kiichi词典
    希一词典如果您对我发言中的某些词汇感到不解,请看这份词典。这里汇集了尽可能多的您可能会感到不解而我不会解释的发言。关于这里没提到的东西,建议您bdfs。如果遇到这里没写的可以在评论里。展开目录目录希一词典您句末句号瓦塔西早/早上好(在非早晨的时间段)重返/9/2k-1持续......
  • leetcode面试经典150题- 45. 跳跃游戏 II
    https://leetcode.cn/problems/jump-game-ii/description/?envType=study-plan-v2&envId=top-interview-150gopackageleetcode150import"testing"funcTestJump2(t*testing.T){nums:=[]int{5,9,3,2,1,0,2,3,3,1,0,0}res:=j......
  • 【刷力扣】876. 链表的中间结点
    876.链表的中间结点依旧是“力扣新手村”里的题,我的思路只有解法1,然而解法2更妙,学习学习!解法1:单指针法1.经过一次遍历求出链表的长度。2.再次遍历找到链表的中间结点。classSolution{public:ListNode*middleNode(ListNode*head){intsize=0;//记录链......
  • 【刷力扣】1342. 将数字变成 0 的操作次数
    1342.将数字变成0的操作次数这题是包含在“力扣新手村”里的题,按直接模拟的方法来写很简单。不过我一点儿都没有想到位运算的写法,看了看别人的题解,学习了一下下~解法1:直接模拟直接按题意模拟:1.判断num是否为0。2.num不为0,进行一次操作:(1)奇数:num=num-1;(2)偶数:num=num......
  • STM32&IIC与SPI详解
    单片机里的通信协议其实蛮多的,IIC;SPI;MQTT;CAN;包括串口也是一种通信协议。而串口通信虽然实现了全双工,但需要至少三根线,为了节省这一根线的成本,于是IIC诞生了。目录一.IIC协议1.IIC的结构2.IIC的特点3.IIC的通信时序4.具体配置(32HAL库版)二.SPI协议1.SPI的结构2.SPI的特......
  • 3152. 特殊数组 II
    3152.特殊数组II题目链接:3152.特殊数组II代码如下:classSolution{public:vector<bool>isArraySpecial(vector<int>&nums,vector<vector<int>>&queries){vector<int>d(nums.size());//std::iota(numbers.......
  • 力扣刷题之2940.找到Alice和Bob可能相遇的建筑
    题干描述给你一个下标从 0 开始的正整数数组 heights ,其中 heights[i] 表示第 i 栋建筑的高度。如果一个人在建筑 i ,且存在 i<j 的建筑 j 满足 heights[i]<heights[j] ,那么这个人可以移动到建筑 j 。给你另外一个数组 queries ,其中 queries[i]=[......
  • (算法)猜数字⼤⼩II————<暴搜->记忆化搜索->动态规划>
    1.题⽬链接:375.猜数字⼤⼩II2.题⽬描述:3.解法(暴搜->记忆化搜索):算法思路:暴搜:a.递归含义:给dfs⼀个使命,给他⼀个区间[left,right],返回在这个区间上能完胜的最⼩费⽤;b.函数体:选择[left,right]区间上的任意⼀个数作为头结点,然后递归分析左右⼦树。求出所有情况......