如何在C++中顺时针旋转矩阵外圈n步?
仅顺时针旋转矩阵外圈n步的解决方案
我来帮你搞定这个问题!你之前用的是整个矩阵旋转的逻辑(通常是转90度的经典写法),当然没法只转外圈,我们换个更精准的思路来实现你要的效果。
核心思路
要只转外圈,我们可以把外圈的元素单独提取出来形成一个环形数组,旋转这个数组后再放回原矩阵,这样就不会影响内圈的元素了。具体分四步走:
定位外圈边界
对于m行k列的矩阵,外圈由四个部分组成:- 顶部行:第0行,从左到右所有列
- 右侧列:最后一列,从第二行到最后一行(跳过顶部行已经取过的元素)
- 底部行:最后一行,从倒数第二列到第一列(反向,跳过右侧列取过的元素)
- 左侧列:第一列,从倒数第二行到第二行(反向,跳过底部和顶部行取过的元素)
提取外圈元素
按照上面的顺序,把外圈所有元素收集到一个一维列表里,形成一个环形的序列。处理旋转步数
外圈元素的总数是2*(m + k - 2),为了避免重复旋转(比如转15步和转1步在14个元素的外圈效果一样),我们把n取模这个总数,得到有效步数n = n % total。旋转并放回元素
顺时针旋转n步,等价于把环形数组的最后n个元素移到最前面(比如数组[a,b,c,d]顺时针转1步就变成[d,a,b,c])。之后再把旋转后的元素按原来的顺序填回矩阵的外圈位置即可。
代码实现(以Java为例,其他语言思路一致)
public static void rotateOuterCircle(int[][] matrix, int n) { int rows = matrix.length; if (rows == 0) return; int cols = matrix[0].length; // 如果只有一行/一列,没有外圈可转,直接返回 if (cols == 0 || rows == 1 || cols == 1) return; // 第一步:提取外圈元素到列表 List<Integer> outerElements = new ArrayList<>(); // 顶部行:左到右 for (int j = 0; j < cols; j++) { outerElements.add(matrix[0][j]); } // 右侧列:上到下(跳过顶部行最后一个元素) for (int i = 1; i < rows; i++) { outerElements.add(matrix[i][cols - 1]); } // 底部行:右到左(跳过右侧列最后一个元素) for (int j = cols - 2; j >= 0; j--) { outerElements.add(matrix[rows - 1][j]); } // 左侧列:下到上(跳过底部行第一个和顶部行第一个元素) for (int i = rows - 2; i >= 1; i--) { outerElements.add(matrix[i][0]); } int totalElements = outerElements.size(); n = n % totalElements; if (n == 0) return; // 步数为0,无需旋转 // 第二步:旋转列表(顺时针n步 = 把最后n个元素移到前面) List<Integer> rotatedElements = new ArrayList<>(); rotatedElements.addAll(outerElements.subList(totalElements - n, totalElements)); rotatedElements.addAll(outerElements.subList(0, totalElements - n)); // 第三步:把旋转后的元素放回矩阵 int index = 0; // 填充顶部行 for (int j = 0; j < cols; j++) { matrix[0][j] = rotatedElements.get(index++); } // 填充右侧列 for (int i = 1; i < rows; i++) { matrix[i][cols - 1] = rotatedElements.get(index++); } // 填充底部行 for (int j = cols - 2; j >= 0; j--) { matrix[rows - 1][j] = rotatedElements.get(index++); } // 填充左侧列 for (int i = rows - 2; i >= 1; i--) { matrix[i][0] = rotatedElements.get(index++); } }
测试你的示例
原4×5矩阵:
1 2 3 4 5 6 7 8 9 0 5 4 2 5 7 8 2 7 9 3
调用rotateOuterCircle(matrix, 1)后,输出完全符合你的预期:
6 1 2 3 4 5 7 8 9 5 8 4 2 5 0 2 7 9 3 7
为什么你之前的逻辑不适用?
你之前写的代码是整个矩阵旋转90度的经典写法,它会递归处理矩阵的每一层(包括内圈),而且是固定旋转90度,不是按指定步数旋转,所以完全不符合"仅转外圈n步"的需求。我们上面的方法只针对最外层元素操作,精准实现了你要的效果。
内容的提问来源于stack exchange,提问作者Vivank
相关产品推荐
相关产品推荐

