Python一行代码解决矩阵旋转

本文介绍了一种使用Python解决矩阵旋转和打印问题的方法。通过逆时针旋转矩阵并取出第一行,实现了从外向里以顺时针顺序打印矩阵元素。文章提供了详细的代码示例,包括矩阵转置、顺时针旋转和逆时针旋转的实现。

今天刷《剑指offer》的时候碰到这样一道题:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

思路:可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作,例如 :

1 2 3
4 5 6
7 8 9

利用pop输出并且删除第一行后,再进行一次逆时针旋转,就变成:

6 9
5 8
4 7

然后,继续重复上述操作即可。

最主要的在于实现矩阵的逆时针操作。关于矩阵的旋转有好几种,转置、顺时针、逆时针,下面直接上代码,用一行python代码实现这三种操作。

矩阵转置:

matrix = [[1,2,3], [4,5,6], [7,8,9]]
matrix = map(list, zip(*matrix))
print(matrix)

>>>[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

矩阵顺时针旋转:先把矩阵上下翻转,然后在转置一下

matrix = [[1,2,3], [4,5,6], [7,8,9]]
matrix[:] = map(list,zip(*matrix[::-1]))
print(matrix)

>>>[[7, 4, 1], [8, 5, 2], [9, 6, 3]]

矩阵逆时针旋转:先把矩阵转置一下,然后在上下翻转

matrix = [[1,2,3], [4,5,6], [7,8,9]]
matrix[:] = map(list,zip(*matrix))[::-1]
print(matrix)

>>>[[3, 6, 9], [2, 5, 8], [1, 4, 7]]

下面是完整的解题代码:

# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        result = []
        while(matrix):
            result += matrix.pop(0)
            if not matrix or not matrix[0]:
                break
            # 将矩阵逆时针旋转
            matrix[:] = map(list, zip(*matrix))[::-1]
        return result

参考文献:一行代码搞定矩阵旋转

<think> 根据用户的问题,用户希望查找使用Python求解旋转矩阵代码。这里的“求解旋转矩阵”可能有多重含义,但根据提供的引用,我们可以归纳为以下几种情况: 1. 旋转一个矩阵(例如图像处理中的旋转操作) 2. 由旋转角度(如欧拉角)生成旋转矩阵 3. 旋转矩阵与其他表示(如四元数)之间的转换 但是,用户的问题中并没有明确指定是哪种情况。因此,我们需要根据引用内容提供几种常见的旋转矩阵相关代码示例,并尽量覆盖用户可能的需求。 根据引用[1]和[2],有关于矩阵旋转(即旋转一个矩阵)的代码,例如顺时针旋转90度(通常用于图像处理)。引用[3]和[4]则涉及到旋转矩阵的表示(如由欧拉角生成旋转矩阵,或者旋转矩阵转换为四元数)以及旋转矩阵的合成。 考虑到用户问题中并没有明确,我们将提供两个常见场景的代码: 1. 旋转一个给定的矩阵(例如二维数组)90度(顺时针或逆时针) 2. 根据给定的旋转角度(例如绕x轴、y轴、z轴旋转)生成相应的旋转矩阵。 另外,引用[3]中提到了旋转矩阵转换为四元数,引用[4]则演示了旋转矩阵的合成以及旋转顺序的重要性。如果用户需要,我们也可以提供这些转换的代码。 由于用户的问题比较宽泛,我们将先提供两个最可能的代码示例,并给出解释,然后再提供一些相关问题供用户选择,以便进一步明确需求。 ### 示例1:旋转一个矩阵(二维数组)90度 在图像处理或矩阵操作中,旋转矩阵90度是一个常见操作。下面是一个顺时针旋转90度的函数(引用[1]中提供了先转置再翻转每一行的方法): ```python def rotate_matrix_clockwise(matrix): n = len(matrix) # 转置矩阵 for i in range(n): for j in range(i, n): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] # 翻转每一行(实现顺时针旋转) for i in range(n): matrix[i] = matrix[i][::-1] return matrix ``` 注意:上述代码会修改原始矩阵。如果不想修改原始矩阵,可以先创建副本。 逆时针旋转90度可以类似地实现,先转置然后翻转每一列(或者先翻转每一行再转置): ```python def rotate_matrix_counterclockwise(matrix): n = len(matrix) # 翻转每一行 for i in range(n): matrix[i] = matrix[i][::-1] # 转置矩阵 for i in range(n): for j in range(i, n): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] return matrix ``` ### 示例2:根据欧拉角生成旋转矩阵 在三维空间中,旋转矩阵通常由绕三个坐标轴的旋转角度(欧拉角)来定义。注意旋转顺序很重要(引用[4]提到旋转顺序不同会导致结果不同)。这里我们按照绕Z轴、Y轴、X轴的顺序(常见的顺序)来生成旋转矩阵。 ```python import numpy as np def rotation_matrix_from_euler(angles): """根据欧拉角生成旋转矩阵 参数: angles: 一个包含三个角度的元组 (绕x轴旋转角度, 绕y轴旋转角度, 绕z轴旋转角度)(单位:弧度) 返回: 3x3的旋转矩阵 """ alpha = angles[2] # 绕z轴旋转角度 beta = angles[1] # 绕y轴旋转角度 gamma = angles[0] # 绕x轴旋转角度 # 绕x轴旋转矩阵 Rx = np.array([ [1, 0, 0], [0, np.cos(gamma), -np.sin(gamma)], [0, np.sin(gamma), np.cos(gamma)] ]) # 绕y轴旋转矩阵 Ry = np.array([ [np.cos(beta), 0, np.sin(beta)], [0, 1, 0], [-np.sin(beta), 0, np.cos(beta)] ]) # 绕z轴旋转矩阵 Rz = np.array([ [np.cos(alpha), -np.sin(alpha), 0], [np.sin(alpha), np.cos(alpha), 0], [0, 0, 1] ]) # 组合旋转矩阵(这里按照ZYX顺序,即先绕z轴,再绕y轴,最后绕x轴) R = Rz @ Ry @ Rx # 注意矩阵乘法的顺序 return R ``` 注意:欧拉角的旋转顺序非常重要,常见的顺序有ZYX、XYZ等。上面的代码采用ZYX顺序(即先绕Z轴,再绕Y轴,最后绕X轴)。如果用户需要其他顺序,可以调整矩阵乘法的顺序。 ### 示例3:旋转矩阵转换为四元数(引用[3]) 如果用户需要将旋转矩阵转换为四元数,可以使用第三方库(如`pyquaternion`)来实现: ```python from pyquaternion import Quaternion def rotation_matrix_to_quaternion(rotation_matrix): """将3x3旋转矩阵转换为四元数""" q = Quaternion(matrix=rotation_matrix) return q ``` ### 注意事项 - 旋转矩阵的定义有主动旋转和被动旋转(坐标系旋转)之分,使用时需注意。 - 旋转顺序对结果有重要影响(引用[4])。 ### 相关问题 如果用户的需求不在上述示例中,或者需要更深入的信息,我们可以提供以下相关问题供用户选择: §§相关问题§§ 1. 如何实现矩阵的任意角度旋转(例如45度)? 2. 如何将旋转矩阵转换为欧拉角? 3. 如何用四元数生成旋转矩阵4. 旋转矩阵在三维空间中的合成顺序为什么重要? 5. 如何实现三维空间中绕任意轴的旋转? 希望上述代码和解释能够帮助用户。如果用户有更具体的需求,可以进一步询问。 </think> 以下是使用Python求解旋转矩阵的几种常见方法及代码实现,结合旋转矩阵的不同应用场景: ### 1. 矩阵旋转(90°倍数旋转) 适用于图像处理或二维矩阵旋转操作: ```python def rotate_matrix_90(matrix): """顺时针旋转90度""" n = len(matrix) # 转置矩阵 for i in range(n): for j in range(i, n): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] # 水平翻转 for i in range(n): matrix[i] = matrix[i][::-1] return matrix # 示例使用 original = [[1,2,3],[4,5,6],[7,8,9]] rotated = rotate_matrix_90(original) print(rotated) # 输出: [[7,4,1],[8,5,2],[9,6,3]] ``` 此方法通过转置+翻转实现$O(n^2)$时间复杂度的矩阵旋转[^1][^2]。 ### 2. 欧拉角转旋转矩阵 适用于三维空间中的坐标系变换: ```python import numpy as np def euler_to_rotation(roll, pitch, yaw): """欧拉角(弧度)转旋转矩阵 (Z-Y-X顺序)""" # 绕X轴旋转 Rx = np.array([ [1, 0, 0], [0, np.cos(roll), -np.sin(roll)], [0, np.sin(roll), np.cos(roll)] ]) # 绕Y轴旋转 Ry = np.array([ [np.cos(pitch), 0, np.sin(pitch)], [0, 1, 0], [-np.sin(pitch), 0, np.cos(pitch)] ]) # 绕Z轴旋转 Rz = np.array([ [np.cos(yaw), -np.sin(yaw), 0], [np.sin(yaw), np.cos(yaw), 0], [0, 0, 1] ]) # 组合旋转 (Z-Y-X顺序) return Rz @ Ry @ Rx # 示例:绕Z轴旋转30度 rotation_matrix = euler_to_rotation(0, 0, np.radians(30)) print(rotation_matrix) ``` 输出为: $$ \begin{bmatrix} 0.866 & -0.5 & 0 \\ 0.5 & 0.866 & 0 \\ 0 & 0 & 1 \end{bmatrix} $$ 注意旋转顺序会影响结果(XYZ/YZX等不同顺序产生不同矩阵)[^4]。 ### 3. 旋转矩阵转四元数 适用于机器人学和三维动画: ```python from pyquaternion import Quaternion def rotation_to_quaternion(matrix): """旋转矩阵转四元数""" return Quaternion(matrix=matrix) # 示例使用 rot_matrix = [[0, -1, 0], [1, 0, 0], [0, 0, 1]] # 绕Z轴90°旋转 q = rotation_to_quaternion(rot_matrix) print(f"四元数: w={q.w}, x={q.x}, y={q.y}, z={q.z}") ``` 输出示例:`四元数: w=0.707, x=0, y=0, z=0.707`[^3] ### 4. 绕任意轴旋转 适用于三维空间中的通用旋转: ```python def rotation_around_axis(axis, theta): """罗德里格斯旋转公式""" axis = np.asarray(axis) / np.linalg.norm(axis) # 单位化 a = np.cos(theta/2) b, c, d = -axis * np.sin(theta/2) return np.array([ [a*a+b*b-c*c-d*d, 2*(b*c-a*d), 2*(b*d+a*c)], [2*(b*c+a*d), a*a+c*c-b*b-d*d, 2*(c*d-a*b)], [2*(b*d-a*c), 2*(c*d+a*b), a*a+d*d-b*b-c*c] ]) # 示例:绕[1,1,0]轴旋转45度 axis = [1, 1, 0] angle = np.radians(45) rot_mat = rotation_around_axis(axis, angle) ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值