剑指offer面试题29:顺时针打印矩阵

索引请参考:系列目录
题目:

  • 输入一个矩阵,按照从外向里顺时针依次大一每一个数字

  • 示例:

  • 输入
    在这里插入图片描述

  • 输出:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10


思路:
(1)分析循环打印条件

  • 假设 行数为 height 列数 width
    • (1)打印第一圈左上角的坐标(0,0),第二圈的左上角坐标(1,1),以此类推注:做左上角坐标中行坐标和列坐标总是相同的 即在矩阵中选取左上角为(start,start)的一圈作为分析目标

    • (2) 对于5*5矩阵矩阵而言。最后一圈只有一个数字,对应坐标(2,2)5 > 2 * 2
      在这里插入图片描述

    • 对于6*6矩阵,最后一圈有4个数字,左上角坐标为(2,2)6 > 2 * 2
      在这里插入图片描述

    • 对于4*6矩阵有6个数字,左上角坐标为(1 * 1)6 > 1 * 2 && 4 > 1 * 2
      在这里插入图片描述

    • 对于6*4矩阵,最后一圈有6个数字,左上角的坐标为(1,1)6 > 1 * 2 && 4 > 1 * 2
      在这里插入图片描述

    • 让循环继续的条件是 width > startX * 2 && height > startY * 2

(2)打印一圈的功能

  • (1)可以分为四步
    • 第一步: 从左往右打印
    • 第二步:从上往下打印
    • 第三步:从右往左打印
    • 第四步:从下往上打印
    • 每一步根据起始和终止坐标用一个循环姐可以打印一行或者是一列

(2)分析每一步的前提条件

  • 第一步总是需要的,因为打印一圈至少需要一步
  • 如果只有一行,则只需要第一步 即第二部的前提条件是种植的行号大于起始行
  • 第三步的前提条件是矩阵内至少右两行两列 即除了要求终止行号大于起始行号,还要求终止列号大于起始列号
  • 第三步的前提条件是至少有三行两列 即要求终止行号比起始行好至少大于2,同时终止列号大于起始列号

打印一圈代码

void printCircle(const std::vector<std::vector<int>> & matrix, std::vector<int> & result, const int start) {

	int endX = matrix[0].size() - 1 - start;
	int endY = matrix.size() - 1 - start;
	//从左往右打印
	for (int x = start; x < endX; x++)
		result.push_back(matrix[start][x]);
	//从上往下打印
	if (start < endY)
	{
		for (int y = start + 1; y <= endY; y++)
			result.push_back(matrix[y][endX]);
	}
	//从右往左打印
	if (start < endY && start < endX)
	{
		for (int x = endX - 1; x >= start; x--)
			result.push_back(matrix[endY][x]);
	}
	//从下往上打印
	if (start < endY - 1 && start < endX)
	{
		for (int y = endY - 1; y >= start + 1; y--)
			result.push_back(matrix[y][start]);
	}
}

循环打印函数

std::vector<int> printMatrix(const std::vector<std::vector<int>> & matrix) {

	int start = 0;
	int width = matrix[0].size();
	int height = matrix.size();
	std::vector<int>result;
	while (width > start * 2 && height > start * 2)
	{
		printCircle(matrix, result, start);
		++start;
	}
	return result;
}

评注:该题看似比较难,其实并未涉及数据结构与算法的太多知识,相当于一种思想。多加练习即可掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值