<代码随想录二刷>二分查找 | 双指针 | 滑动窗口 | 枚举模拟(四)

简介: <代码随想录二刷>二分查找 | 双指针 | 滑动窗口 | 枚举模拟

4、枚举模拟法

59.螺旋矩阵 II

题目描述

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

示例 1:


c9edd2a10847555fc69467b3c0c97c71.png

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

示例 2:

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


思路分析:

方法一:模拟(循环不变量原则)


根据卡尔大佬的说法,求解本题依然是要坚持循环不变量原则。


模拟顺时针画矩阵的过程:


填充上行从左到右

填充右列从上到下

填充下行从右到左

填充左列从下到上

由外向内一圈一圈这么画下去。


可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人。


89f599e34566a53126d79d65fce164df.png


这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。


这也是坚持了每条边左闭右开的原则。


一些同学做这道题目之所以一直写不好,代码越写越乱。


就是因为在画每一条边的时候,一会左开又闭,一会左闭右闭,一会又来左闭右开,岂能不乱。


方法二


生成一个 n×n 空矩阵 res,随后模拟整个向内环绕的填入过程:


定义当前左右上下边界 l,r,u,d,初始值 num = 1,迭代终止值 sum= n * n;


当 num <= sum 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后:num++,得到下一个需要填入的数字;


更新边界:例如从左到右填完后,上边界 u++,相当于上边界向内缩 1。


使用num <= sum而不是l < r || u < d作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。


最终返回 res即可


参考代码

方法一

#include<bits/stdc++.h>
using namespace std;
vector<vector<int>> generateMatrix(int n) {
  int startX = 0,startY = 0;//循环起始下标
  vector<vector<int>> res(n,vector<int>(n,0));//定义矩阵
  int loop = n / 2;//循环层数
  int offSet = 1;//每次循环遍历需要减少的元素个数
  int cnt = 0;//进行矩阵赋值
  int i,j;
  while(loop--) {
    i = startX;
    j = startY;
    //从左到右
    for(; j<startY+n-offSet; j++) {
      res[i][j] = ++cnt;
    }
    //结束的j刚好就是下一次循环需要用的纵坐标
    //从上到下
    for(; i<startX+n-offSet; i++) {
      res[i][j] = ++cnt;
    }
    //从右到左
    for(; j>startY; j--) {
      res[i][j] = ++cnt;
    }
    //从下到上
    for(; i>startX; i--) {
      res[i][j] = ++cnt;
    }
    //
    startX++;//更新下一次起始下标
    startY++;
    offSet+=2;
  }
  if(n%2==1) {//如果n是奇数,更新中心点.
    res[n/2][n/2] = ++cnt;
  }
  return res;
}

方法二

#include<bits/stdc++.h>
using namespace std;
vector<vector<int>> generateMatrix(int n) {
  vector<vector<int>> res(n,vector<int>(n,0));
  int u = 0,d = n - 1,l = 0,r = n-1;
  int num = 1;
  while(num<=n*n){
    //从左到右
    for(int i = l; i <= r;i++) {
      res[u][i] = num++;
    }
    u++;
    //从上到下
    for(int i = u;i<=d;i++){
      res[i][r] = num++;
    }
    r--;
    //从右到左
    for(int i = r;i>=l;i--){
      res[d][i] = num++;
    }
    d--;
    //从下到上 
    for(int i = d;i>=u;i--) {
      res[i][l] = num++;
    }
    l++;
  }
  return res;
}

54. 螺旋矩阵

题目描述

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

4d79de6dac1a33d93924e3017130b5e0.png


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

示例 2:

cb528643a67e353e7d454bc6229acbc6.png

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

思路分析

和上面的题思路二很相似,但本题不同的是会出现矩形;,所以中间的for循环也要对sum进行限制,防止减成0后,后面的for还执行.

参考代码

#include<bits/stdc++.h>
using namespace std;
vector<int> spiralOrder(vector<vector<int>>& matrix) {
  if(matrix.size()==0) {
    return {};
  }
  vector<int> res;
  int n = matrix.size(),m = matrix[0].size();
  int u = 0,l = 0,d = n - 1,r = m - 1;
  int sum = n * m;
  while(sum) {
    //从左到右
    for(int i = l; i <= r&&sum; i++) {
      res.push_back(matrix[u][i]);
      sum--;
    }
    u++;
    //从上到下
    for(int i = u; i<=d&&sum; i++) {
      res.push_back(matrix[i][r]);
      sum--;
    }
    r--;
    //从右到左
    for(int i = r; i>=l&&sum; i--) {
      res.push_back(matrix[d][i]);
      sum--;
    }
    d--;
    //从下到上
    for(int i = d; i>=u&&sum; i--) {
      res.push_back(matrix[i][l] );
      sum--;
    }
    l++;
  }
  return res;
}

如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。

创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客

相关文章
|
3月前
|
存储 搜索推荐 C语言
深入C语言指针,使代码更加灵活(二)
深入C语言指针,使代码更加灵活(二)
|
3月前
|
存储 程序员 编译器
深入C语言指针,使代码更加灵活(一)
深入C语言指针,使代码更加灵活(一)
|
3月前
|
C语言
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
|
5月前
|
存储 大数据 测试技术
掌握 GoLang 中的指针:高效代码的提示和技巧
掌握 GoLang 中的指针:高效代码的提示和技巧
|
7月前
|
Go C++
代码随想录——双指针与滑动窗口(四)
代码随想录——双指针与滑动窗口(四)
|
7月前
|
Go C++
代码随想录——双指针/滑动窗口(三)
代码随想录——双指针/滑动窗口(三)
|
2月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
215 13
|
3月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
47 0
|
4月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
176 4
|
5月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)