【问题标题】:Can this O(n) Matrix Rotation algorithm be done in place and remain O(n)?这个 O(n) 矩阵旋转算法可以在原地完成并保持 O(n) 吗?
【发布时间】:2020-03-20 14:28:19
【问题描述】:

问题:

是否可以调整下面发布的算法以使用相同的数组(表示二维矩阵)进行顺时针旋转而不是使用第二个数组并且仍然保持 O(n) 复杂度?

代码:

import java.util.Random;

public class MatrixRotation {

  public static void main(String[] args) {
    int dimension = 5;

    int[] array = generate(dimension);
    print(array, dimension);

    int[] clockwise = clockwise(array, dimension);
    print(clockwise, dimension);
  }

  //Generate a matrix with random values
  private static int[] generate(int dimension) {
    Random rand = new Random();
    int[] array = new int[dimension * dimension];
    for(int i = 0; i < array.length; i++) {
      array[i] = rand.nextInt(10);
    }
    return array;
  }

  //Rotates the matrix clockwise by calculating where the value's position should be after the rotation
  private static int[] clockwise(int[] array, int dimension) {
    int[] rotated = new int[array.length];
    int baseCount = dimension;

    for(int i = 0; i < array.length; i++) {
      int remainder = i % dimension;

      if(remainder == 0)
        baseCount--;

      int position = baseCount + (dimension * remainder);

      //I suspect I can do some kinda swapping functionality here but am stumped

      rotated[position] = array[i];
    }

    return rotated;
  }

  //Used to display the matrix
  private static void print(int[] array, int dimension) {
    for(int i = 0; i < array.length; i++) {
      if(i % dimension == 0) 
        System.out.println();
      System.out.print(array[i] + " ");
    }
    System.out.println();
  }
}

样本输出:

1 7 4 1 4 
2 3 5 2 9 
4 3 9 3 1 
5 8 7 5 6 
3 3 7 2 5 

3 5 4 2 1 
3 8 3 3 7 
7 7 9 5 4 
2 5 3 2 1 
5 6 1 9 4 

背景:

前几天我正在阅读一个关于一维数组中表示的矩阵旋转的问题,并决定尝试解决这个问题。通过计算旋转后值的下一个位置,我成功地创建了旋转算法。目前,我正在尝试确定是否有办法将其保持为 O(n),同时通过将其保持在同一个数组中来减少使用的空间。关于如何实现这一点的任何想法?

【问题讨论】:

    标签: java matrix rotation


    【解决方案1】:

    我找到了一个可行的解决方案!我无法确定如何使它与发布的算法一起工作,但是一旦我从头开始设计它并从一开始就进行旋转交换,我就找到了一个具有相同复杂性的解决方案(基本上)。我设计它的想法是通过“洋葱层”从外到内工作,方法是找到每一层的角,然后旋转它们以及它们的相对方向相邻。比如:

        ↓                      ↓                     ↓
        5 5 8 2 1 ←          7 5 8 2 5           7 2 8 2 5  
        9 4 8 2 3            9 4 8 2 3 ←         9 4 8 2 5 
        6 3 7 5 4            6 3 7 5 4         → 6 3 7 5 4 ←       Ect...
        2 6 4 2 7          → 2 6 4 2 7           5 6 4 2 7 
      → 7 0 7 5 5            5 0 7 5 1           5 0 7 3 1 
                ↑                  ↑                 ↑
    

    对于每一层。

    代码:

      private static int[] clockwise2(int[] array, int dimension) {
        int layers = dimension / 2; //Total layers of the onion
        //Loop through the layers
        for (int i = 0; i < layers; i++) {
          int layerWidth = dimension - 2 * i; //Current layer width
    
          int topStart = i + dimension * i; //Top left corner
          int rightStart = topStart + (layerWidth - 1); //Top right corner
          int bottomStart = (array.length - 1) - topStart; //Bottom right corner
          int leftStart = bottomStart - (layerWidth - 1); //Bottom left corner
    
          //Loop values in current layer
          for (int j = 0; j < layerWidth - 1; j++) {
            int topIndex = topStart + j; //Move right
            int rightIndex = rightStart + dimension * j; //Move down
            int bottomIndex = bottomStart - j; //Move left
            int leftIndex = leftStart - dimension * j; //Move up
    
            //Swap the values in a circular direction
            int temp = array[topIndex];
            array[topIndex] = array[leftIndex];
            array[leftIndex] = array[bottomIndex];
            array[bottomIndex] = array[rightIndex];
            array[rightIndex] = temp;
          }
        }
    
        return array;
      }
    

    【讨论】:

      猜你喜欢
      • 2023-01-19
      • 1970-01-01
      • 2017-02-10
      • 2016-01-27
      • 2023-03-25
      • 2021-09-25
      • 1970-01-01
      • 2015-08-11
      • 2021-07-04
      相关资源
      最近更新 更多