zoukankan      html  css  js  c++  java
  • Hackerrank

    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)),空间一样。

     1 import re
     2 
     3 def get2DMatrix(n, m, val):
     4     return [[val for j in xrange(m)] for i in xrange(n)]
     5     
     6 def rotate(a, r):
     7     # n is guaranteed to be even
     8     n = len(a)
     9     m = len(a[0])
    10     s = getDisplace(n, m)
    11     s = displacePow(s, r)
    12     b = get2DMatrix(n, m, 0)
    13     for i in xrange(n):
    14         for j in xrange(m):
    15             b[i][j] = a[s[i * m + j] / m][s[i * m + j] % m]
    16     return b
    17     
    18 def getDisplace(n, m):
    19     s = range(n * m)
    20     i = 0
    21     while i < n / 2 and i < m / 2:
    22         rr = n - 2 * i
    23         cc = m - 2 * i
    24         for j in xrange(1, rr, 1):
    25             #left
    26             s[(j + i) * m + i] = (j - 1 + i) * m + i
    27         for j in xrange(1, cc, 1):
    28             #down
    29             s[(rr - 1 + i) * m + (j + i)] = (rr - 1 + i) * m + (j - 1 + i)
    30         for j in xrange(rr - 2, -1, -1):
    31             #right
    32             s[(j + i) * m + (cc - 1 + i)] = (j + 1 + i) * m + (cc - 1 + i)
    33         for j in xrange(cc - 2, -1, -1):
    34             #top
    35             s[i * m + (j + i)] = i * m + (j + 1 + i)
    36         i += 1
    37     return s
    38 
    39 def multiply(a, b):
    40     n = len(a)
    41     c = []
    42     for i in xrange(n):
    43         c.append(a[b[i]])
    44     return c
    45     
    46 def displacePow(a, k):
    47     if k == 1:
    48         return a[:]
    49     a2 = displacePow(a, k >> 1)
    50     if k & 1:
    51         return multiply(multiply(a2, a2), a)
    52     else:
    53         return multiply(a2, a2)
    54     
    55 if __name__ == '__main__':
    56     n, m, r = map(int, re.split('s+', raw_input().strip()))
    57     a = []
    58     for i in xrange(n):
    59         a.append(map(int, re.split('s+', raw_input().strip())))
    60     a = rotate(a, r)
    61     for i in xrange(n):
    62         print(' '.join(map(str, a[i])))
    63         
  • 相关阅读:
    C++第11课 迭代器与仿函数 (二)
    C++第11课 迭代器与仿函数 (一)
    Python语法的应用
    Python面试
    02_Python之基础编程
    01_Python之_学前准备
    Sorting It All Out (拓扑排序) poj1094
    Codeforces Global Round 13 Editorial补题
    今天做题做到了并查集相关的内容~简单介绍一下关于并查集的东西
    留言板
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/4691096.html
Copyright © 2011-2022 走看看