第二篇:矩阵旋转

今天是释然发题解的第二天,以后每一天都会和大家分享学习路上的心得,希望和大家一起进步,一起享受coding的乐趣。
本文约2700字,预计阅读10分钟
昨天我们学习了矩阵翻转,忘记的小伙伴们可以看一下哦:

矩阵翻转

今天我们来聊一聊矩阵的旋转,明天和大家分享结构和链表的相关题目:


矩阵的旋转又分为:顺时针旋转和逆时针旋转

顺时针旋转:

指将整个矩阵进行顺指针方向的旋转
例如:把下面这个矩阵旋转

1 2 3
4 5 6
7 8 9

旋转成

7 4 1
8 5 2
9 6 3

那么我们应该如何去旋转呢?

矩阵的旋转其实有一定的规律:
我们看 1 这个元素由(0,0)变成了(0,2)
2 这个元素由(0,1)变成了(1,2)
3 这个元素由(0,2)变成了(2,2)
第一行元素假设初始的位置为(i,j)变化后的横坐标是不是就是j,纵坐标应该是和原来的横坐标有关,我们带入n-1试试发现是符合的(n代表阶数)

我们再来测试一下第二行数据
4 这个元素由(1,0)变成了(0,1)
5 这个元素由(1,1)变成了(1,1)
6 这个元素由(1,2)变成了(2,1)

果然变化后的横坐标就是j,纵坐标发现不符合n-1,那我们要考虑是否与原先的i有关系了,发现n-1-i,刚好满足这样的规律,在验证一下刚刚的三组数据,完全符合,此时i都是0,导致我们把i忽略了

因此我们发现矩阵的旋转和原来的坐标是有密切联系的,这一点非常重要

那么矩阵的旋转的关系式我们就找到了:

//我们假设原数组是x[][],另一个数组是y[][]
 y[i][j]=x[j][n-1-i];
 //我们用两层循环就可以得到旋转的数组
 for(i=0;i<N;i++)
	  for(j=0;j<N;j++)
	     y[i][j]=x[j][n-1-i];

是不是很简单呢,就是很简单的找规律呢。
那么逆时针就迎刃而解了,大家先自己推导一下,后面直接上代码

逆时针旋转:

同理,跟变化前的横纵坐标有密切联系,我们根据上面的规律可以轻松推出:

//我们假设原数组是x[][],另一个数组是y[][]
y[i][j]=x[N-1-j][i];
//我们用两层循环就可以得到旋转的数组
for(i=0;i<N;i++)
	  for(j=0;j<N;j++)
	     y[i][j]=x[N-1-j][i];

接下来我们来活学活用:

例题:Matrix Rotation

Problem Description:Give you a n * n matrix, if you rotate it 90
degrees, we call it 1-Matrix, if you rotate it 180 degrees, we call it
2-Matrix, etc … This is said if you rotate the Matrix 90*k degrees,
then we call it k-Matrix. Now, your task is to calculate all the sum
of i-Matrix (0<= i<= k).

Input:There multiple test cases. Each test case begins with one
integer n(1 <= n <= 10), following n lines, each line contains n
integers, describe the original matrix, then a single line contains a
k (1 <= k <= 10^8)described above. Process to end of file.
Output:For each case, output the sum of all the i-Matrix (0<= i<= k)
in n lines. Each line there are n integers separated by one space.
Note that there is no extra space at the end of each line.

Sample
Input
3
1 2 3
2 3 4
3 4 5
10
Sample Output
33 32 31
34 33 32
35 34 33

我们多去联系一下英文的题目,这样我们的学习既可以锻炼我们的解题能力,又可以锻炼我们的英文水平

那么这道题的意思很简单:我们把一个n阶的矩阵,不停地进行旋转,然后再相加,最后输出求和的矩阵就可以啦

首先我们用一个函数来对矩阵进行旋转

//因为n是<=10的
void rotate(int x[][10],int N)
{
	int i,j;
	int y[10][10];
	for(i=0;i<N;i++)
	  for(j=0;j<N;j++)
	     y[i][j]=x[N-1-j][i];
	//因为要返回旋转后的矩阵,我们再把矩阵还原
	for(i=0;i<N;i++)
	  for(j=0;j<N;j++)
	     x[i][j]=y[i][j];	
}  

我们用二层循环进行输入,输入完以后对每次旋转过后的矩阵要进行求和,这个时候我们开一个循环:

//每一次旋转后相加
for( m=1;m<=4;m++)
	{
		rotate(a,n);
		for(i=0;i<n;i++)
		   for(j=0;j<n;j++)
		      c[i][j]+=a[i][j];
	}

我们知道没四次旋转其实就是一组,我们只要看进行了几组旋转,在第一组循环后乘上一个组数,再加上最后多出来的那几组就是本题的答案了

//我们再用两个循环乘上组数
for(i=0;i<n;i++)
	for(j=0;j<n;j++)
		c[i][j]=k*c[i][j];

```cpp
//我们再计算多出来的那几次旋转
for(m=1;m<=l%4;m++)
{
	rotate(a,n);
	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			c[i][j]+=a[i][j];
}

最后注意,题目中加粗的这句Note that there is no extra space at the end of each line. 意思是我们最后一个数字输出后不能有多余的空格,那我们就选择输出前n-1个数据+空格,最后一个数据单独输出就行

然后再加上本身第一次初始的矩阵就可以输出了

for(i=0;i<n;i++)
{
	for(j=0;j<n-1;j++)
		cout<<c[i][j]+b[i][j]<<' ';
	//我们用b[][]来保存初始的数组
	//c[][]这个数组是求和过的
	//a[][]这个数组不停地进行旋转	
	cout<<c[i][n-1]+b[i][n-1]<<endl;
}

好了,今天的矩阵旋转就到这里,还有什么不理解的地方,你细细品就行,我觉得已经讲得很清楚了
释然每天发布一点自己学习的知识,希望2年后我们也能在ACM的赛场上见面,一起去追寻自己的程序猿之路吧!

后期也会和大家一起分享学习心得和学习经验呢,明天我们不见不散哦!

下期预告:

结构和链表

如果大家有什么建议或者要求请后台留言,释然也想和大家一起进步呀!
联系方式:shirandexiaowo@foxmail.com

  • 4
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shirandexiaowo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值