【算法】顺时针打印矩阵

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

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

要想到能一圈一圈的打印,每一圈就是从左到右,再从上到下,再从右到左,再从下到上。每次打印完更新圈的左上角点。剩下的就是找规律,确定边界条件,画图分析起来方便。

最后就是整个矩阵打印完的标志,左上角点超出行或列的一半就结束了,因为这个每一圈左右上下都是对称的,到矩阵边缘的距离是一样的,超出一半势必有重合而且撞墙。

#include<bits/stdc++.h>
using namespace std;

/*本题的坐标图*/
//-------------X
//\
//\
//\
//\
//Y
void PrintMatrixInCircle(int** numbers, int columns, int rows, int start);
void printNumber(int number);


// 参数:
//        numbers:       矩阵(二维数组)的首地址
//        columns:       矩阵总的列数
//        rows:          矩阵总的行数
// 输出:
//        调用输出顺时针圈的函数,完成题意(顺时针打印矩阵)
void PrintMatrixClockwisely(int** numbers, int columns, int rows) {
	//输入合法性检查
	if(numbers == nullptr || columns <= 0 || rows <= 0)
		return;

	int start = 0;//最开始圈的起始点从左上角(0,0)开始

	//规律:当打印完毕时,起始点会超出行列长度至少其一的一半
	while(columns > start * 2 && rows > start * 2) {
		//输出这个顺时针圈
		PrintMatrixInCircle(numbers, columns, rows, start);
		//输出完了这圈,起始点向右下移动一步,成为新的顺时针圈起始点
		++start;
	}
}

// 参数:
//        numbers:       矩阵(二维数组)的首地址
//        columns:       矩阵总的列数
//        rows:          矩阵总的行数
//        start:         圈的起始处在左上角,相对坐标(start,start)
// 输出:
//        矩阵的一个顺时针圈
void PrintMatrixInCircle(int** numbers, int columns, int rows, int start) {
	//因为圈离边界的距离是确定的,以此计算圈右下角的相对坐标(endX,endY)
	int endX = columns - 1 - start;
	int endY = rows - 1 - start;

	//从左到右打印一行,无论什么情况都要打印的
	for(int i = start; i <= endX; ++i) {//x坐标从起始到结尾
		int number = numbers[start][i];//即行数确定,列号在增
		printNumber(number);
	}

	//从上到下打印一列
	if(start < endY) {//只有当计算出的起始点在终止点上方时才需要打印
		for(int i = start + 1; i <= endY; ++i) {//y坐标从起始到结尾
			int number = numbers[i][endX];//即列数确定,行号在增
			printNumber(number);
		}
	}

	//从右到左打印一行
	if(start < endX && start < endY) {//这是最下面的一行,要求终止点确实在右下
		for(int i = endX - 1; i >= start; --i) {//x坐标从末尾到起始
			int number = numbers[endY][i];//即行数确定,列号在减
			printNumber(number);
		}
	}

	//从下到上打印一行
	if(start < endX && start < endY - 1) {//最后一步也要求在右下方,且高度至少差一个格子才需要上来
		for(int i = endY - 1; i >= start + 1; --i) {//y坐标从末尾到起始
			int number = numbers[i][start];//即列数确定,行号在减
			printNumber(number);
		}
	}
}

//格式化输出
void printNumber(int number) {
	printf("%d\t", number);
}


/*
1    2    3    4    5
6    7    8    9    10
11   12   13   14   15
16   17   18   19   20
21   22   23   24   25
*/
int main() {
	int rows=5,columns=5;
	//建立矩阵(二维数组)并初始化 
	int** numbers = new int*[rows]; 
	for(int i = 0; i < rows; ++i) {
		numbers[i] = new int[columns];
		for(int j = 0; j < columns; ++j) {
			numbers[i][j] = i * columns + j + 1;
		}
	}

	PrintMatrixClockwisely(numbers, columns, rows);
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值