You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中不借助额外数组原地转换二维数组?

原地实现二维数组循环右下移一位的方案

方案一:分两步实现(每行右移+每列下移)

这种方法逻辑直观,空间复杂度仅为O(1)(仅使用几个临时变量),时间复杂度O(rows*cols),和原代码效率完全一致。

核心思路:每个元素最终要移动到((i+1)%rows, (j+1)%cols),等价于先将每行元素循环右移一位,再将每列元素循环下移一位(顺序调换为“先下移再右移”,结果完全相同)。

实现代码

public static void TransformArrayInPlace(int[,] matrix)
{
    int rows = matrix.GetLength(0);
    int cols = matrix.GetLength(1);

    // 第一步:每行循环右移一位
    for (int i = 0; i < rows; i++)
    {
        int temp = matrix[i, cols - 1];
        for (int j = cols - 1; j > 0; j--)
        {
            matrix[i, j] = matrix[i, j - 1];
        }
        matrix[i, 0] = temp;
    }

    // 第二步:每列循环下移一位
    for (int j = 0; j < cols; j++)
    {
        int temp = matrix[rows - 1, j];
        for (int i = rows - 1; i > 0; i--)
        {
            matrix[i, j] = matrix[i - 1, j];
        }
        matrix[0, j] = temp;
    }
}

public static void Main(string[] args)
{
    int[,] matrix = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    TransformArrayInPlace(matrix);

    // 输出转换后的数组
    for (int i = 0; i < matrix.GetLength(0); i++)
    {
        for (int j = 0; j < matrix.GetLength(1); j++)
        {
            Console.Write(matrix[i, j] + " ");
        }
        Console.WriteLine();
    }
}

效果验证

原数组:

1 2 3
4 5 6
7 8 9

每行右移后:

3 1 2
6 4 5
9 7 8

每列下移后:

9 7 8
3 1 2
6 4 5

与原代码使用临时数组的输出完全一致。


方案二:循环链替换法(严格O(1)空间)

如果需要完全避免任何额外数组(包括标记访问状态的数组),可以采用循环链替换思路:每个元素的移动路径会形成闭合循环链,仅用一个临时变量保存当前值,即可完成链内元素的依次替换。

实现代码

public static void TransformArrayInPlace(int[,] matrix)
{
    int rows = matrix.GetLength(0);
    int cols = matrix.GetLength(1);
    int chainCount = Gcd(rows, cols);

    for (int k = 0; k < chainCount; k++)
    {
        int currentI = k / cols;
        int currentJ = k % cols;
        int temp = matrix[currentI, currentJ];

        while (true)
        {
            int nextI = (currentI + 1) % rows;
            int nextJ = (currentJ + 1) % cols;
            if (nextI == k / cols && nextJ == k % cols)
                break;

            int nextTemp = matrix[nextI, nextJ];
            matrix[nextI, nextJ] = temp;
            temp = nextTemp;

            currentI = nextI;
            currentJ = nextJ;
        }
        matrix[k / cols, k % cols] = temp;
    }
}

// 辅助方法:计算最大公约数
private static int Gcd(int a, int b)
{
    while (b != 0)
    {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

思路说明

以3x3数组为例,存在3个独立循环链:

  • (0,0) → (1,1) → (2,2) → (0,0)
  • (0,1) → (1,2) → (2,0) → (0,1)
  • (0,2) → (1,0) → (2,1) → (0,2)

遍历每个循环链的起点,依次将链内元素替换到目标位置,全程仅用一个临时变量保存被覆盖的值,无额外内存开销。


优化建议

  • 小规模数组优先选方案一,代码更易读、易维护。
  • 超大数组且对内存占用要求极高时,选方案二,完全无额外数组开销。
  • 两种方案时间复杂度均为O(rows*cols),与原代码效率一致,无性能损失。

内容的提问来源于stack exchange,提问作者satanmoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:55:08