【问题标题】:Change elements in an array更改数组中的元素
【发布时间】:2017-03-08 21:14:08
【问题描述】:

我已经为这个不寻常的任务困惑了几天,想找出一个合适的算法。假设我有二维数组:

int[][] jagged = new int[4][];
jagged[0] = new int[4] { 1, 2, 3, 4 };
jagged[1] = new int[4] { 5, 6, 7, 8 };
jagged[2] = new int[4] { 9, 10, 11, 12 };
jagged[3] = new int[4] { 13, 14, 15, 16 };

我怎样才能把这个矩阵逆时针旋转成下面这样?

1  2  3  4             2 3 4 8           3 4 8 12
5  6  7  8    -->      1 7 11 12   -->   2 11 10 16 
9  10 11 12            5 6 10 16         1 7  6  15 
13 14 15 16            9 13 14 15        5 9  13 14

二维数组可以有多种维度。我的意思是 2x3 或 3x4。

我尝试使用以下算法,但它只能旋转 90 度:

int [,] newArray = new int[4,4];

for (int i=3;i>=0;--i)
{
    for (int j=0;j<4;++j)
    {
         newArray[j,3-i] = array[i,j];
    }
}

如果我改变增量,那么它不会给我任何东西。也许还有其他解决方案?

【问题讨论】:

    标签: c# arrays


    【解决方案1】:

    假设数组的每个“正方形”都独立旋转。
    您可以使用以下代码 sn-p:

    const int ArraySize = 4;
    int[,] array = 
                    {
                        { 2, 3, 4, 8 },
                        { 1, 7, 11, 12 },
                        { 5, 6, 10, 16 },
                        { 9, 13, 14, 15 }
                    };
    
    for (int r = (ArraySize - 1) / 2; r >= 0; r--)
    {
        int start = r;
        int end = ArraySize - r - 1;
        int saveTopLeft = array[start, start];
    
        // Top
        for (int i = start; i <= end - 1; i++)
            array[start, i] = array[start, i + 1];
    
        // Right
        for (int i = start; i <= end - 1; i++)
            array[i, end] = array[i + 1, end];
    
        // Bottom
        for (int i = end; i >= start + 1; i--)
            array[end, i] = array[end, i - 1];
    
        // Left
        for (int i = end; i >= start + 2; i--)
            array[i, start] = array[i - 1, start];
    
        // Saved element
        array[start + 1, start] = saveTopLeft;
    }
    

    【讨论】:

    • 是否可以进行尽可能多的旋转。比如转两三圈?
    • Dmitry,如果我有另一个维度的矩阵,那么我应该添加/删除for 循环吗?您是否知道任何其他无需重写代码的解决方案?
    • @StepUp 是的,可以重复运行此代码。如果你有矩阵的第三维,恐怕解决方案会复杂得多。
    • 拜托,你能写出适合各种矩阵大小的代码吗?
    【解决方案2】:

    我知道这个问题已经得到解答,但我想为nxm 的一般矩阵做这个。它考虑了矩阵只有一列或一行的极端情况。

    public static void Rotate(int[,] matrix)
    {
        // Specific cases when matrix has one only row or column
        if (matrix.GetLength(0) == 1 || matrix.GetLength(1) == 1)
            RotateOneRowOrColumn(matrix);
        else
        {
            int min = Math.Min(matrix.GetLength(0), matrix.GetLength(1)),
            b = min / 2, r = min % 2;
    
            for (int d = 0; d < b + r; d++)
            {
                int bkp = matrix[d, d];
                ShiftRow(matrix, d, d, matrix.GetLength(1) - d - 1, true);
                ShiftColumn(matrix, matrix.GetLength(1) - d - 1, d, matrix.GetLength(0) - d - 1, false);
                ShiftRow(matrix, matrix.GetLength(0) - d - 1, d, matrix.GetLength(1) - d - 1, false);
                ShiftColumn(matrix, d, d + 1, matrix.GetLength(0) - d - 1, true);
                if (matrix.GetLength(0) - 2 * d - 1 >= 1)
                    matrix[d + 1, d] = bkp;
           }
        }
    }
    
    private static void RotateOneRowOrColumn(int[,] matrix)
    {
        bool isRow = matrix.GetLength(0) == 1;
        int s = 0, e = (isRow ? matrix.GetLength(1) : matrix.GetLength(0)) - 1;
    
        while (s < e)
        {
            if (isRow)
                Swap(matrix, 0, s, 0, e);
            else
                Swap(matrix, s, 0, e, 0);
            s++; e--;
        }
    }
    
    public static void Swap(int[,] matrix, int from_x, int from_y, int to_x, int to_y)
    {
        //It doesn't verifies whether the indices are correct or not
        int bkp = matrix[to_x, to_y];
        matrix[to_x, to_y] = matrix[from_x, from_y];
        matrix[from_x, from_y] = bkp;
    }
    
    public static void ShiftColumn(int[,] matrix, int col, int start, int end,  bool down)
    {
        for (int i = down ? end - 1 : start + 1; (down && i >= start) || (!down && i <= end); i += down ? -1 : 1)
        { matrix[i + (down ? 1 : -1), col] = matrix[i, col]; }
    }
    
     public static void ShiftRow(int[,] matrix, int row, int start, int end, bool left)
    {
        for (int j = left ? start + 1 : end - 1; (left && j <= end) || (!left && j >= start); j += (left ? 1 : -1))
        { matrix[row, j + (left ? -1 : 1)] = matrix[row, j]; }
    }
    

    【讨论】:

    • @StepUp,根据我所做的一些测试,我相信我的代码适用于每个二维矩阵。做你自己的测试,如果你发现任何问题,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    相关资源
    最近更新 更多