精选算法题(2)——矩阵螺旋输出

简介: 精选算法题(2)——矩阵螺旋输出

题目描述:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。


例如,如果输入4*4的矩阵:


1 2 3 4;5 6 7 8;9 10 11 12;13 14 15 16。


则依次打印出数字:


1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10。


解题思路:

本题为了将矩阵顺时针螺旋输出。如下图所示,对每一圈而言,就是先获取第一行,再拿到最后一列,再拿最后一行,最后拿第一列,确定好对应的位置关系,用4个循环即可实现。考虑到可能会碰上行列不一致的情况,所以圈数要取行数和列数最小值的一半。另外,我发现当矩阵为3行4列时,第2圈只有6和7,此时用常规代码会将6重复获取两次,为了避免该情况发生,用mask作为数据是否获取的位置标识。

测试代码:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define min(a,b) (a < b ? a : b)
vector<int> getSpiralData(vector<vector<int>> inputs);
int main()
{
  // 输入矩阵
  vector<vector<int>> inputs = {
    {1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16},{17,18,19,20},{21,22,23,24}
  };
  // 输出输入
  cout << "输入:" << endl;
  for (int i = 0; i < inputs.size(); ++i)
  {
    for (int j = 0; j < inputs[0].size(); ++j)
    {
      cout << inputs[i][j] << " ";
    }
    cout << endl;
  }
  // 输出螺旋矩阵
  vector<int> output = getSpiralData(inputs);
  // 输出结果
  cout << "输出:" << endl;
  for (int i = 0; i < output.size(); ++i)
  {
    cout << output[i] << " ";
  }
  cout << endl;
  system("pause");
  return 0;
}
// 输出螺旋矩阵
vector<int> getSpiralData(vector<vector<int>> inputs)
{
  // 定义行列数
  int row = inputs.size();
  int col = inputs[0].size();
  // 定义起始点
  int startr = 0;
  int startc = 0;
  // 定义圈数,offset=0为第一圈
  int offset = 0;
  // 初始化输出
  vector<int> outputs;
  // 初始化掩膜,用来避免数据重复存储
  vector<vector<bool>> mask(row,vector<bool>(col,false));
  // 当行列不一致时,取最小值/2作为圈数
  int turns = (min(row, col) + 1 ) / 2;
  // 单圈存储
  while (turns)
  {
    int i = startr;
    int j = startc;
    // 顺时针第一行
    for (j = startc; j < col - offset; j++)
    {
      if (!mask[i][j])
      {
        outputs.push_back(inputs[i][j]);
        mask[i][j] = true;
      }
    }
    j--;
    // 顺时针最后一列
    for (i = startr + 1; i < row - offset; i++)
    {
      if (!mask[i][j])
      {
        outputs.push_back(inputs[i][j]);
        mask[i][j] = true;
      }
    }
    i--;
    // 顺时针最后一行
    for (j = col - offset - 2; j >= startc; j--)
    {
      if (!mask[i][j])
      {
        outputs.push_back(inputs[i][j]);
        mask[i][j] = true;
      }
    }
    j++;
    // 顺时针第一列
    for (i = row - offset - 2; i > startr; i--)
    {
      if (!mask[i][j])
      {
        outputs.push_back(inputs[i][j]);
        mask[i][j] = true;
      }
    }
    i++;
    // 圈数步进,下一圈的初始点的x和y值均+1
    offset++;
    startr++;
    startc++;
    turns--;
  }
  return outputs;
}

测试结果:

图1 4*4矩阵结果

图2 6*4矩阵结果

      如图1所示,4*4的矩阵按顺时针顺利获取,如图2所示6*4的矩阵也能按顺时针顺利获取。感兴趣的可以用3*4行试试,如果不用mask进行判断,得到的结果如图3所示,最后的6是重复的,这是因为第三个循环中j>=startc导致,但是这个等号也是很有必要的,为此加上mask即可解决该麻烦,正确结果如图4所示。

图3 错误的数据

图4 正确的数据

      如果代码有什么需要改进的或者有什么bug,欢迎评论留言,我会及时更正以免误导他人~

      如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

相关文章
|
1月前
|
算法 测试技术 C++
【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II
【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II
|
1月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-48 算法训练 关联矩阵
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-48 算法训练 关联矩阵
43 0
|
1月前
|
算法 测试技术 C#
【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II
【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II
|
19天前
|
存储 算法 数据挖掘
python5种算法模拟螺旋、分层填充、递归、迭代、分治实现螺旋矩阵ll【力扣题59】
python5种算法模拟螺旋、分层填充、递归、迭代、分治实现螺旋矩阵ll【力扣题59】
|
15天前
|
算法
【经典LeetCode算法题目专栏分类】【第6期】二分查找系列:x的平方根、有效完全平方数、搜索二位矩阵、寻找旋转排序数组最小值
【经典LeetCode算法题目专栏分类】【第6期】二分查找系列:x的平方根、有效完全平方数、搜索二位矩阵、寻找旋转排序数组最小值
|
15天前
|
算法
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
|
1月前
|
算法 测试技术 编译器
【算法 | 实验18】在字符矩阵中查找给定字符串的所有匹配项
题目描述 题目 在字符矩阵中查找给定字符串的所有匹配项 给定一个M×N字符矩阵,以及一个字符串S,找到在矩阵中所有可能的连续字符组成的S的次数。所谓的连续字符,是指一个字符可以和位于其上下左右,左上左下,右上右下8个方向的字符组成字符串。用回溯法求解。
50 1
|
1月前
|
算法
【免费】面向多微网网络结构设计的大规模二进制矩阵优化算法
【免费】面向多微网网络结构设计的大规模二进制矩阵优化算法
|
1月前
|
算法 测试技术 Serverless
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
|
1月前
|
算法 测试技术 C++
【字符串】【 LCP】【C++算法】2573找出对应 LCP 矩阵的字符串
【字符串】【 LCP】【C++算法】2573找出对应 LCP 矩阵的字符串