如何在C#中顺时针旋转m*n矩阵?方阵右旋高效实现需求
1. C#中实现m×n矩阵的顺时针旋转90度
首先要明确:非方阵的m×n矩阵顺时针旋转90度后,会变成n×m的矩阵。核心思路要么是先反转每一行再转置,要么直接通过坐标映射构造新矩阵,下面给你两种常用实现方式:
举个直观例子:原3×2矩阵
1 2 3 4 5 6
顺时针旋转90度后会变成2×3矩阵:
5 3 1 6 4 2
用List<List<int>>实现(适配动态大小矩阵)
public static List<List<int>> RotateClockwise(List<List<int>> matrix) { if (matrix == null || matrix.Count == 0 || matrix[0].Count == 0) return new List<List<int>>(); int rows = matrix.Count; int cols = matrix[0].Count; var rotated = new List<List<int>>(); // 初始化旋转后的n×m矩阵,从原矩阵最后一行到第一行取对应列元素 for (int i = 0; i < cols; i++) { rotated.Add(new List<int>()); for (int j = rows - 1; j >= 0; j--) { rotated[i].Add(matrix[j][i]); } } return rotated; }
用二维数组int[,]实现
public static int[,] RotateClockwise(int[,] matrix) { if (matrix == null || matrix.GetLength(0) == 0 || matrix.GetLength(1) == 0) return new int[0, 0]; int rows = matrix.GetLength(0); int cols = matrix.GetLength(1); int[,] rotated = new int[cols, rows]; // 坐标映射:原矩阵的(i,j)元素 → 旋转后位于(j, rows-1 -i)位置 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { rotated[j, rows - 1 - i] = matrix[i, j]; } } return rotated; }
2. 给动态方阵类实现高效右旋功能
三次调用RotateLeft()确实绕了远路,毕竟每次左旋都要遍历整个矩阵,三次下来操作量是单次右旋的3倍左右。下面给你两种高效的原地实现方案,直接完成顺时针旋转90度:
方案1:转置+反转行(简洁易读,适合大多数场景)
假设你的类内部用int[,] m_a存储矩阵,代码如下:
public void RotateRight() { int n = m_a.GetLength(0); if (n <= 1) return; // 1×1矩阵无需旋转 // 第一步:转置矩阵(行和列互换) for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int temp = m_a[i, j]; m_a[i, j] = m_a[j, i]; m_a[j, i] = temp; } } // 第二步:反转每一行 for (int i = 0; i < n; i++) { for (int j = 0; j < n / 2; j++) { int temp = m_a[i, j]; m_a[i, j] = m_a[i, n - 1 - j]; m_a[i, n - 1 - j] = temp; } } }
方案2:分层旋转(原地操作,内存效率拉满)
如果追求极致的内存利用率(不需要额外空间),可以把矩阵拆成多个环形层,每层内的元素直接交换位置:
public void RotateRight() { int n = m_a.GetLength(0); if (n <= 1) return; for (int layer = 0; layer < n / 2; layer++) { int first = layer; int last = n - 1 - layer; for (int i = first; i < last; i++) { int offset = i - first; // 保存顶部元素 int top = m_a[first, i]; // 左侧元素移到顶部 m_a[first, i] = m_a[last - offset, first]; // 底部元素移到左侧 m_a[last - offset, first] = m_a[last, last - offset]; // 右侧元素移到底部 m_a[last, last - offset] = m_a[i, last]; // 顶部元素移到右侧 m_a[i, last] = top; } } }
这两种方案都只需要遍历一次矩阵(或两次线性遍历),无论时间还是内存效率都远优于三次左旋的方式。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

