Python算法题集_旋转图像

题目48:旋转图像

本文为Python算法题集之一的代码示例

1. 示例说明

  • 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

    你必须在原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

    示例 1:

    img

    输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
    输出:[[7,4,1],[8,5,2],[9,6,3]]
    

    示例 2:

    img

    输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
    输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
    

    提示:

    • n == matrix.length == matrix[i].length
    • 1 <= n <= 20
    • -1000 <= matrix[i][j] <= 1000

2. 题目解析

- 题意分解

  1. 本题为矩阵旋转,主要的要求是在空间复杂度上
  2. 本题主要是图像旋转的坐标映射处理
  3. 基本的解法是采用结果矩阵来处理,将会是标准解法【虽然题目不允许】

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 旋转90度,四个角会同时变换,其他位置也是同样的情形

    2. 通过反转和旋转矩阵,也可以达成旋转图像的目的


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题很难超时,超时测试用例自行生成,代码详见【4. 最优算法】

3. 代码展开

1) 标准求解【矩阵复本】

标准代码是双重计算量,居然还能超过95%,网络波动影响真是大 指标优异,超越95%在这里插入图片描述

import CheckFuncPerf as cfp

def rotate_base(matrix):
 ilen = len(matrix)
 idiv = ilen // 2
 m1 = []
 for iIdx in range(ilen):
     m1.append([0 for x in range(ilen)])
 m1[idiv][idiv] = matrix[idiv][idiv]
 for id in range(ilen):
     for jd in range(idiv):
         m1[id][jd] = matrix[ilen - jd - 1][id]
         m1[jd][ilen - id - 1] = matrix[id][jd]
         m1[ilen - id - 1][ilen - jd - 1] = matrix[jd][ilen - id - 1]
         m1[ilen - jd - 1][id] = matrix[ilen - id - 1][ilen - jd - 1]
 for id in range(ilen):
     for jd in range(ilen):
         matrix[id][jd] = m1[id][jd]

import random,copy
matrix = []
for iIdx in range(1000):
 matrix.append([random.randint(0, 10) for x in range(1000)])
matrixCopy = copy.deepcopy(matrix)
result = cfp.getTimeMemoryStr(rotate_base, matrixCopy)
print(result['msg'])

# 运行结果
函数 rotate_base 的运行时间为 384.08 ms;内存使用量为 484.00 KB

2) 改进版一【矩阵转置+矩阵反转】

执行一次转置,然后左右反转,空间复杂度O(1),结果达成 虚假指标,超越87%在这里插入图片描述

import CheckFuncPerf as cfp

def rotate_ext1(matrix):
 ilen = len(matrix)
 idiv = ilen // 2
 for iIdx in range(ilen):
     for jIdx in range(iIdx):
         matrix[iIdx][jIdx], matrix[jIdx][iIdx] = matrix[jIdx][iIdx], matrix[iIdx][jIdx]
 for iIdx in range(ilen):
     for jIdx in range(idiv):
         matrix[iIdx][jIdx], matrix[iIdx][ilen-jIdx-1] = matrix[iIdx][ilen-jIdx-1], matrix[iIdx][jIdx]

import random,copy
matrix = []
for iIdx in range(1000):
 matrix.append([random.randint(0, 10) for x in range(1000)])
matrixCopy = copy.deepcopy(matrix)
result = cfp.getTimeMemoryStr(rotate_ext1, matrixCopy)
print(result['msg'])

# 运行结果
函数 rotate_ext1 的运行时间为 152.03 ms;内存使用量为 0.00 KB

3) 改进版二【四值旋转】

同时旋转四个值,一次性算完,执行计算最少,代码简洁优雅 极速狂飙,超越95%在这里插入图片描述

import CheckFuncPerf as cfp

def rotate_ext2(matrix):
 m1 = matrix
 ilen, idiv = len(matrix), ilen // 2
 for id in range(idiv):
     for jd in range(id, ilen-id-1):
         m1[id][jd], m1[jd][ilen-id-1], m1[ilen-id-1][ilen-jd-1], m1[ilen-jd-1][id] = \
             m1[ilen-jd-1][id], m1[id][jd], m1[jd][ilen-id-1], m1[ilen-id-1][ilen-jd-1]

import random,copy
matrix = []
for iIdx in range(1000):
 matrix.append([random.randint(0, 10) for x in range(1000)])
matrixCopy = copy.deepcopy(matrix)
result = cfp.getTimeMemoryStr(rotate_ext2, matrixCopy)
print(result['msg'])

# 运行结果
函数 rotate_ext2 的运行时间为 146.02 ms;内存使用量为 0.00 KB

4. 最优算法

根据本地日志分析,最优算法为第3种rotate_ext2

import random,copy
matrix = []
for iIdx in range(1000):
    matrix.append([random.randint(0, 10) for x in range(1000)])
matrixCopy = copy.deepcopy(matrix)

# 算法本地速度实测比较
函数 rotate_base 的运行时间为 384.08 ms;内存使用量为 484.00 KB
函数 rotate_ext1 的运行时间为 152.03 ms;内存使用量为 0.00 KB
函数 rotate_ext2 的运行时间为 146.02 ms;内存使用量为 0.00 KB

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

长孤秋落

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

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

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

打赏作者

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

抵扣说明:

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

余额充值