题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如,如果输入如下4 X 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.
 
 
思想:
一圈一圈的打印,这道题难点在于何时中止打印。
 
图为在矩阵中某一圈,length为矩阵长度,width为矩阵宽度,坐标值为数组下标。

对于我们这道题来说,只要有内圈可以进入下一圈就是以第一圈(0,0)    第二圈 (1,1) ……的规律做每一圈的起点

现在考虑以下标(i,i)为起点的一圈,其图像为length为矩阵长度,width为矩阵宽度

打印过程是四个for循环以此为上-》右-》下-》左顺时针遍历

按照图我们开始遍历第i圈

//注意四个角的元素不能重复
//上 行i 列i length-i-1
for (int j=i; j <= length-i-1; j++) {
result.push_back(matrix[i][j]);
}
//右 列 length-i-1 行i+1
for (int j= i+1; j <= width - i - 1; j++) {
result.push_back(matrix[j][length-i-1]);
}
//下 行width-i-1 列length-2-1 到i
for (int j = length-i-2; j >= i; j--) {
result.push_back(matrix[width-i-1][j]);
}
//左 列i 行 width-i-2 到 i+1
for (int j = width-i-2; j > i; j--) {
result.push_back(matrix[j][i]);
}

  

  

现在一圈完了,下一圈会不会有什么突发状况?

思考:假设下一圈就结束循环了,那么可能遇到什么情况,下一圈不再是一个完整矩形(指的是长宽都大于1的矩阵)而是有四种可能。我们之所以分析是要看这几种情况对我们四个for循环是否都适用

1.没有元素

2.只有一个元素

3.只有一行元素

4.只有一列元素

好的,现在我们知道了所有可能的形状。那进入到这几种情况我们就要考虑了。

1.本圈矩形的长宽只要任意一个为0就结束循环,没有元素了 条件 宽0长0   length-2i<=0或width-2i<=0  

此时直接跳出循环即可,四个for循环都不满足

2.只有一个元素和只有一行元素  就是我们只需要进行 顺势针打印的上面部分,此时条件是 宽1长若干  (width-2i==1且length-2i大于1)化简此时 width=2i-i

//打印一行没有问题,按道理来说是不是之后的打印都不应该做

观察下

右面打印的判断条件   int j= i+1; j <= width - i - 1; j++   因为宽度为1  初始    width为2i+1   代入for循环判断不满足   j=i+1<  i条件

下面打印的判断条件   int j = length-i-2; j >= i; j--   假设length无穷大,那可进入for循环从左到右打印

左面打印的判断条件类似右面,因宽度为1本身就可限制

总结:因长度大于1,宽度等于1出现重复打印情况如下:

所以我们在   顺时针上面对应的for结束,右侧下面左侧的for可以避免。但是我们下侧for循环就需要有判断条件,为   if(宽度为1则下侧for循环不执行)

3.只有一行元素  就是我们可以顺时针打印 上面 和 左面的部分,此时条件是 宽若干长1  (width-2i大于1且length-2i==1)

类似一行的情况,要给左侧for循环加判断条件  if(长度为1可以不打左侧,因为右侧打完了)

ok,那基于上面的分析我们知道了只要下一圈有元素,我们就可以i++,四个for遍历下一圈,加上我们的if条件。即使出现特殊情况也不必担心。

那下一圈有元素的条件就是非没有元素的条件(length-2*i>0)&&(width-2*i>0)

综上所述,总结一下 对于单行、单列要考虑左右、上下打印条件的相互制约。

给出代码和运行截图:

 class Solution {
public:
static vector<int> printMatrix(vector<vector<int> > matrix) {
if (matrix.size() == ) return vector<int>();
int width = matrix.size(), length = matrix[].size();//r,c为矩阵长宽
int i = ;
vector<int> result;
while ((length - * i > ) && (width - * i > ))
{
//上侧
for (int j = i; j <= length - i - ; j++) {
result.push_back(matrix[i][j]);
} //右侧
for (int j = i + ; j <= width - i - ; j++) {
result.push_back(matrix[j][length - i - ]);
}
//下侧
if (width - * i != ) {//宽度为1不要有右到左打印一遍了,上侧已经打了
for (int j = length - i - ; j >= i; j--) {
result.push_back(matrix[width - i - ][j]);
}
}
//左侧
if (length - * i != ) {//长度为1不要再由下到上打印一遍了,右侧从上到下打了
for (int j = width - i - ; j > i; j--) {
result.push_back(matrix[j][i]);
}
}
i++; }
return result;
} };

运行截图:

附上一个小知识点:vectot<int> 的push_back函数会像数组尾部填数据。预先申请好大小后vector<int> a(5); 用 push_back时会扩容的去填,前面的5个数都是0。

我误认为要先申请空间才能向里添加数据了。

最后,感谢阅读文章,如有疏漏,欢迎指正。

现在转了一圈,要结束了,结束时会出现四种可能,一行、一列、一个、无元素

对于一行的情况,其条件是只

剑指Offer(十九)——顺时针打印矩阵的更多相关文章

  1. 剑指offer 20:顺时针打印矩阵

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数 ...

  2. 剑指offer十九之顺时针打印矩阵

    一.题目 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2, ...

  3. 剑指offer系列17---顺时针打印矩阵(不是很懂)

    package com.exe4.offer; import java.util.ArrayList; /** * 17[题目]输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果 ...

  4. 剑指offer-面试题20.顺时针打印矩阵

    题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字.例如: 输入一个矩阵如下: 则依次打印出数字:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10 这道题的 ...

  5. 剑指offer系列18---顺时针打印矩阵

    [题目]定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数.要求时间复杂度是O(1).push pop min [思路]设计一个辅助栈,当新加入的原数据栈中的数小于辅助栈顶的数时就加 ...

  6. 【剑指Offer】把二叉树打印成多行 解题报告(Python)

    [剑指Offer]把二叉树打印成多行 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...

  7. Go语言实现:【剑指offer】把二叉树打印成多行

    该题目来源于牛客网<剑指offer>专题. 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 需要分层,二维数组. Go语言实现: /** * Definition for ...

  8. 剑指offer-面试题29-顺时针打印矩阵-矩阵

    /* 题目: 输入一个矩阵,按照从外到内顺时针的顺序依次打印每一个数字. */ /* 思路: 1.将打印矩阵看作是打印一个个从外向内的环. 2.每一个环都有一个起始节点,起始节点的坐标*2小于行数和列 ...

  9. 剑指offer系列33-----把二叉树打印成多行

    [题目]从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 方法一:直接打印 package com.exe7.offer; import java.util.LinkedList; i ...

  10. 算法学习之剑指offer(九)

    一 题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). public class Solution ...

随机推荐

  1. OPC—— KepServer.ServerState返回值为3和OPCConfig.exe配置文件的根目录

    做开发没有对电脑的绝对管理员权限的问题,会出现很多意外,调试OPC是总是连接状态有时莫明返回3,提示 not configuration,问题在于: 没有以管理员权限运行OPCConfig.exe,导 ...

  2. hibernate集成ehcahe进行缓存管理

    ehcace是现在非常流行的缓存框架,有轻量.灵活.可扩展.支持集群/分布式等优点. 在项目中,使用ehcace可以对数据进行缓存(一般使用.基于注解.基于aop),使用filter可以对页面进行缓存 ...

  3. Spring——面向切面编程(AOP)详解

    声明:本博客仅仅是一个初学者的学习记录.心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流.一起学习.一起进步的朋友可以加我微信Liu__66666666 这是简单学习一遍之 ...

  4. 写论文与PPT汇报时matlab图片的背景透明处理

    不少同学在使用Word写论文时,将matlab生成的图保存为jpg格式,然后粘贴到文档中.word背景为纯白色,jpg图的缺点没有显示,实际上会存在很大白边,以及放大后不清晰的问题,很影响PPT展示和 ...

  5. thinkphp将上传的临时文件移动到指定目录

    thinkphp将上传的临时文件移动到指定目录 新建common.php文件 <?phpuse think\facade\Env; /** 移动上传的临时文件 * * @img_dir stri ...

  6. 不fq安装 golang tools

    go get -u -v github.com/golang/tools/go/buildutil ln -s $GOPATH/src/github.com/golang/tools $GOPATH/ ...

  7. tomcat下c3p0连接池配置问题

    一.首先如果要使用这个连接池,就需要导入c3p0-0.9.2-pre1.jar架包和支持架包mchange-commons-0.2.jar, 我这里测试使用的是msql数据库 当然也需要导入mysql ...

  8. 浅谈Spring的事务隔离级别与传播性

    浅谈Spring的事务隔离级别与传播性 这篇文章以一个问题开始,如果你知道答案的话就可以跳过不看啦@(o・ェ・)@ Q:在一个批量任务执行的过程中,调用多个子任务时,如果有一些子任务发生异常,只是回滚 ...

  9. 浏览器端获取短信验证码java实现——阿里云短信服务

    需求:浏览器端输入手机号,获取验证码.点击登录,验证验证码是否输入错误.是否超时等情况,一旦校验通过,将用户数据保存到数据中(业务逻辑). 前提:注册阿里用户,开通短信服务,申请key.秘钥.签名.短 ...

  10. 使用Hugo,只需5分钟,轻松搭建一个自己的博客

    前面跟大家介绍过hexo这款静态博客系统,功能强大,基本能满足博客的各种需求.今天,我再跟大家介绍一款优秀的静态博客系统,那就是Hugo. Hugo是由Go语言实现的静态网站生成器.简单.易用.高效. ...