Hackerrank - [Algo] Matrix Rotation
https://www.hackerrank.com/challenges/matrix-rotation-algo
又是一道耗了两小时以上的题,做完了才想起来,这不就是几年前在POJ上做过的一个同类问题么:置换群问题。
给定义一个MxN的矩阵,让你按照从外到内一圈圈地,逆时针旋转R次。如果你打算一次次地转,那就掉坑里了,因为这题的暴力算法比高效算法还难写对。
这其实是置换的一个特例,比如给你一个排列[2, 4, 1, 3],让你按照这个对应关系把长度为4的数组变换R次,问最后的结果。
想到了什么吗?当然是矩阵的快速幂啦!什么矩阵?一个01稀疏矩阵。
[2, 4, 1, 3]可以表示为:
[0 1 0 0]
[0 0 0 1]
[1 0 0 0]
[0 0 1 0]
联系大一学的线性代数知识,这就是这个置换操作对应的左乘变换啊(线性变换)。
把[a, b, c, d]通过一次变换变成了[b, d, a, c]。那么变一亿次之后是什么呢?实际上置换是有循环节的,不过无所谓,有快速幂就不用操心循环节了。
于是变换R次也就是把这矩阵求R次幂,于是快速幂算法就派上用场了。
这题也是类似,只不过构造这个变换矩阵麻烦点,你要看矩阵旋转一次是怎么对应的。得出矩阵以后,求幂就容易了。
时间O(N * M * log(R)),空间一样。
import re def get2DMatrix(n, m, val):
return [[val for j in xrange(m)] for i in xrange(n)] def rotate(a, r):
# n is guaranteed to be even
n = len(a)
m = len(a[0])
s = getDisplace(n, m)
s = displacePow(s, r)
b = get2DMatrix(n, m, 0)
for i in xrange(n):
for j in xrange(m):
b[i][j] = a[s[i * m + j] / m][s[i * m + j] % m]
return b def getDisplace(n, m):
s = range(n * m)
i = 0
while i < n / 2 and i < m / 2:
rr = n - 2 * i
cc = m - 2 * i
for j in xrange(1, rr, 1):
#left
s[(j + i) * m + i] = (j - 1 + i) * m + i
for j in xrange(1, cc, 1):
#down
s[(rr - 1 + i) * m + (j + i)] = (rr - 1 + i) * m + (j - 1 + i)
for j in xrange(rr - 2, -1, -1):
#right
s[(j + i) * m + (cc - 1 + i)] = (j + 1 + i) * m + (cc - 1 + i)
for j in xrange(cc - 2, -1, -1):
#top
s[i * m + (j + i)] = i * m + (j + 1 + i)
i += 1
return s def multiply(a, b):
n = len(a)
c = []
for i in xrange(n):
c.append(a[b[i]])
return c def displacePow(a, k):
if k == 1:
return a[:]
a2 = displacePow(a, k >> 1)
if k & 1:
return multiply(multiply(a2, a2), a)
else:
return multiply(a2, a2) if __name__ == '__main__':
n, m, r = map(int, re.split('\s+', raw_input().strip()))
a = []
for i in xrange(n):
a.append(map(int, re.split('\s+', raw_input().strip())))
a = rotate(a, r)
for i in xrange(n):
print(' '.join(map(str, a[i])))
Hackerrank - [Algo] Matrix Rotation的更多相关文章
- Hackerrank - Game Of Rotation 题解
旋转一个数组以得到最大值. 陷阱就是:不能排序.须要模拟操作旋转,并设计公式计算旋转后的和. 要求是O(n)时间完毕. 原题: https://www.hackerrank.com/challenge ...
- 主成分分析(PCA)原理及R语言实现
原理: 主成分分析 - stanford 主成分分析法 - 智库 主成分分析(Principal Component Analysis)原理 主成分分析及R语言案例 - 文库 主成分分析法的原理应用及 ...
- 【Unity Shaders】学习笔记——SurfaceShader(十一)光照模型
[Unity Shaders]学习笔记——SurfaceShader(十一)光照模型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5664792.html ...
- 【Unity Shaders】法线纹理(Normal Mapping)的实现细节
写在前面 写这篇的目的是为了总结我长期以来的混乱.虽然题目是"法线纹理的实现细节",但其实我想讲的是如何在shader中编程正确使用法线进行光照计算.这里面最让人头大的就是各种矩阵 ...
- 主成分分析(PCA)原理及R语言实现 | dimension reduction降维
如果你的职业定位是数据分析师/计算生物学家,那么不懂PCA.t-SNE的原理就说不过去了吧.跑通软件没什么了不起的,网上那么多教程,copy一下就会.关键是要懂其数学原理,理解算法的假设,适合解决什么 ...
- Must practice programming questions in all languages
To master any programming languages, you need to definitely solve/practice the below-listed problems ...
- Unity Shader-法线贴图(Normal)及其原理
简介 以前经常听说“模型不好看啊,怎么办啊?”答曰“加法线”,”做了个高模,准备烘一下法线贴图”,“有的美术特别屌,直接画法线贴图”.....法线贴图到底是个什么鬼,当年天真的我真的被这个图形学的奇淫 ...
- 相机imu外参标定
1. 第一步初始化imu外参(可以从参数文档中读取,也可以计算出),VINS中处理如下: # Extrinsic parameter between IMU and Camera. estimate_ ...
- VINS(二)Feature Detection and Tracking
系统入口是feature_tracker_node.cpp文件中的main函数 1. 首先创建feature_tracker节点,从配置文件中读取信息(parameters.cpp),包括: ROS中 ...
随机推荐
- pthread_create & pthread_exit
http://www.cppblog.com/saha/articles/189802.html 1. pthread_create #include <pthread.h> ...
- memset赋初值的运用
int ”较“的原则:加法不爆. 极大值:0x7f 较大值:0x3f 较小值:0xc0 极小值:0x80 long long ”较“的原则:加法不爆. 极大值:0x7f 较大值:0x3f 较小值:0x ...
- Git使用02--branch分支, tag版本, 忽略文件 .gitingore
一.分支 # 查看分支 git branch # 创建分支 git branch 分支名 # 切换分支 git checkout name # 创建并切换分支 git checkout -b name ...
- L1 loss L2 loss
https://www.letslearnai.com/2018/03/10/what-are-l1-and-l2-loss-functions.html http://rishy.github.io ...
- 【luogu P3398 仓鼠找sugar】 题解
题目链接:https://www.luogu.org/problemnew/show/P3398 辣鸡树剖1300ms 倍增大法吼啊 #include <cstdio> #include ...
- 【luogu P2299 Mzc和体委的争夺战】 题解
题目链接:https://www.luogu.org/problemnew/show/P2299#sub 裸的迪杰斯特拉(我是在考试前复习一下板子) #include<iostream> ...
- 中小学信息学奥林匹克竞赛-理论知识考点--IP地址
IP地址同身份证号一样,具有唯一性! 每个人都有一个唯一的标识:身份证号. 互联网中的计算机也一样,具有一个唯一的标识:IP地址. IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也 ...
- Java 加密PDF设置密码并添加水印
/** * Project Name:XXX * File Name:EncryptLogFile.java * Date:2016-6-12上午11:56:38 * Copyright (c) 20 ...
- linux多线程编程基本操作(2)
linux c多线程总结: :关于线程和进程 a:使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式.我们知道,在Linux系统下,启动一个新的进程必须分配给 ...
- nineoldandroid 详细使用并且实现drawerlayout侧滑动画
nineoldandroid.view.ViewHelpe是一个为了兼容3.0以下的一个动画开源库 相关函数解读:(第一个参数都为动画对象,第二个为动画属性值的变化表达式) ViewHelper.se ...