在同心圆中旋转2D NxN矩阵

时间:2012-04-15 04:03:36

标签: arrays multidimensional-array

给定2D NxN矩阵,将其可视化为同心圆。您必须找到旋转的矩阵,其中圆中的每个元素在顺时针和逆时针交替的方向上逐层旋转1个位置。所有轮换都应该就地。

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

应该转变为

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

我想到了解决方案

1>对于顺时针旋转,按顺序读取元素

i -> 0 to n-1 and j = 0
j -> 0 to n-1 and i = n-1
i -> n-1 to 0 and j = n-1
j -> n-1 to 0 and i = 0

2 - ;对于逆时针旋转,请按顺序读取元素

j -> 0 to n-1 and i = 0
i -> 0 to n-1 and j = n-1
j -> n-1 to 0 and i = n-1
i -> n-1 to 0 and j = 0

代码

for(int cnt = 0; cnt < n/2; cnt++)
    {   
        if(cnt%2 == 0) // Clockwise
        {   
            i = cnt; j = cnt;
            // while loops for each case
        }
        else // anti-clockwise
        {
            i = cnt; j = cnt;
            // while loops for each case
        }       
}

有没有更好的方法来解决O(n2)或更好的问题?

6 个答案:

答案 0 :(得分:4)

由于您的数组大小为N * N且所需的计算要求每个元素至少访问一次,因此没有比使用2维数组的O(n^2)更好的解决方案。

我认为如果必须在同一阵列上进行一次操作,那么您的解决方案就没问题了。

如果必须在同一输入数组上多次执行此操作,最好从输入数组创建圆。圆的数据结构应该是CLL(循环链表)。因此,多次执行此操作将是件小事,因为您必须根据方向更改存储圆信息的CLL的根元素。

答案 1 :(得分:1)

我认为这可以在O(n)时间内就地解决。

(注:O(N)其中N是矩阵元素的总数)

以下解决方案不使用四个连续循环,但使用一个[X, Y]增量表的小表来描述当前坐标与下一个坐标之间的差异,当下一个坐标无效时(即当前窗口)表格本身的索引是高级的,并且重复查找。该算法以完整窗口开始,并在每次嵌套循环结束时从每一侧减少一个元素。整个过程重复进行,直到定义为[minX, minY, maxX, maxY]的窗口有效(即包含至少2x2个元素)。

此解决方案未实现交换cw和ccw,但这是最容易添加的部分。

function pad(s, n) {
  while(s.length < n)
    s = " " + s;
  return s;
}

// Create a matrix of [WxH] size.
function Matrix(w, h, data) {
  if (Array.isArray(data)) {
    if (data.length !== w * h)
      throw new Error("Data.length has to match the size " + (w * h) + ".");
  }
  else {
    var n = typeof data === "number" ? data : 0.0;
    data = [];
    for (var i = 0; i < w*h; i++) data.push(n);
  }

  this.w = w;
  this.h = h;
  this.data = data;
}

// Get value at [x, y]
Matrix.prototype.get = function(x, y) {
  if (x < 0 || x >= this.w || y < 0 || y >= this.h)
    throw new Error("Index [" + x + ", " + y + "] out of bounds");
  return this.data[y * this.w + x];
}

// Set value at [x, y] and return the previous value.
Matrix.prototype.set = function(x, y, value) {
  if (x < 0 || x >= this.w || y < 0 || y >= this.h)
    throw new Error("Index [" + x + ", " + y + "] out of bounds");

  var i = y * this.w + x;
  var prev = this.data[i];

  this.data[i] = value;
  return prev;
}

// Log the matrix data.
Matrix.prototype.dump = function() {
  var s = "["
  var i = 0;
  for (var y = 0; y < this.h; y++) {
    for (var x = 0; x < this.w; x++, i++) {
      s += pad("" + this.data[i], 2);
      if (x !== this.w - 1)
        s += ","
    }
    if (y !== this.h - 1)
      s += ",\n ";
  }
  s += "]";
  console.log(s);
}

// Shift, `dir` can be "cw" or "ccw".
Matrix.prototype.shift = function(dir) {
  var instructions = {
    cw : [1, 0, 0, 1,-1, 0, 0,-1],
    ccw: [0, 1, 1, 0, 0,-1,-1, 0]
  };
 
  var inst = instructions[dir];

  // A window, shrink by one from each side after the nested loop is done.
  var minX = 0;
  var minY = 0;
  var maxX = this.w - 1;
  var maxY = this.h - 1;

  while (minX < maxX && minY < maxY) {
    // Always start at the top-left corner and iterate.
    var x0 = minX;
    var y0 = minY;
    var v0 = this.get(x0, y0);
    var n = 0;

    for (;;) {
      var x1 = x0 + inst[n + 0];
      var y1 = y0 + inst[n + 1];

      if (x1 < minX || x1 > maxX || y1 < minY || y1 > maxY) {
        n += 2;
        x1 = x0 + inst[n + 0];
        y1 = y0 + inst[n + 1];
      }

      v0 = this.set(x1, y1, v0);

      // Last one.
      if (x1 === minX && y1 === minY)
        break;

      x0 = x1;
      y0 = y1;
    }

    minX++;
    minY++;
    maxX--;
    maxY--;
  }
}

var a = new Matrix(3, 3, [
  1,2,3,
  4,5,6,
  7,8,9,
]);

a.dump();
a.shift("cw");
a.dump();

var b = new Matrix(4, 4, [
  1 ,2 ,3 ,4 ,
  5 ,6 ,7 ,8 ,
  9 ,10,11,12,
  13,14,15,16
]);

b.dump();
b.shift("ccw");
b.dump();

答案 2 :(得分:1)

我最近在求职面试中遇到了这个问题,但我在一小时内未能解决。

然后我回到家,在java中生成下面的代码。它是递归的,我相信它有O(n ^ 2)的复杂性。您还可以在此处查看代码:https://github.com/lotif/rotateMatrix

首先输入(方形)矩阵的维数,然后逐行输入由空格分隔的矩阵数。例如:

3

1 2 3

4 5 6

7 8 9

它将返回以同心圆顺时针旋转的矩阵。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class RotateMatrix {

    public static void main(String args[] ) throws Exception {
        Scanner s = new Scanner(System.in);

        int d = s.nextInt();

        int[][] matrix = new int[d][d];
        for(int i = 0; i < d; i++) {
            for(int j = 0; j < d; j++) {
                matrix[i][j] = Integer.parseInt(s.next());
            }
        }

        matrix = rotate(matrix);

        for(int i = 0; i < matrix.length; i++) {
            for(int j = 0; j < matrix.length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }

        s.close();
    }

    public static int[][] rotate(int[][] matrix) {
        if(matrix == null || matrix.length == 0 || matrix.length == 1) {
            return matrix;
        }

        List<Integer> outerCircle = getOuterCircle(matrix);
        matrix = removeOuterCircle(matrix);
        //rotating outer circle
        outerCircle.add(0, outerCircle.remove(outerCircle.size() - 1));

        matrix = rotate(matrix);

        matrix = addOuterCircle(outerCircle, matrix);

        return matrix;

    }

    private static int[][] addOuterCircle(List<Integer> outerCircle, int[][] matrix) {

        int d = matrix.length + 2;
        int[][] newMatrix = new int[d][d];

        //Adding the outer circle to the matrix
        for(int j = 0; j < d; j++) {
            newMatrix[0][j] = outerCircle.remove(0);
        }
        for(int i = 1; i < d; i++) {
            newMatrix[i][d-1] = outerCircle.remove(0);
        }
        for(int j = d-2; j >= 0; j--) {
            newMatrix[d-1][j] = outerCircle.remove(0);
        }
        for(int i = d-2; i >= 1; i--) {
            newMatrix[i][0] = outerCircle.remove(0);
        }

        //Adding the inner matrix
        for(int i = 0; i < matrix.length; i++) {
            for(int j = 0; j < matrix[i].length; j++) {
                newMatrix[i + 1][j + 1] = matrix[i][j];
            }
        }

        return newMatrix;

    }

    private static List<Integer> getOuterCircle(int[][] matrix) {
        int d = matrix.length;

        List<Integer> outerCircle = new ArrayList<Integer>();

        for(int j = 0; j < d; j++) {
            outerCircle.add(matrix[0][j]);
        }
        for(int i = 1; i < d; i++) {
            outerCircle.add(matrix[i][d-1]);
        }
        for(int j = d-2; j >= 0; j--) {
            outerCircle.add(matrix[d-1][j]);
        }
        for(int i = d-2; i >= 1; i--) {
            outerCircle.add(matrix[i][0]);
        }

        return outerCircle;
    }

    private static int[][] removeOuterCircle(int[][] matrix) {      
        int d = matrix.length;
        int[][] newMatrix = new int[d-2][d-2];

        for(int i = 1; i < d-1; i++) {
            for(int j = 1; j < d-1; j++) {
                newMatrix[i-1][j-1] = matrix[i][j];
            }
        }

        return newMatrix;
    }

}

答案 3 :(得分:0)

public class ShiftArray {
    static void shiftArray(int[][]a, int index, int n) {
       if ((n%2 == 0) && (index >= n/2))
           return;
       if ((n%2 != 0) && (index > n/2))
           return;

       int tempRowTopLast = a[index][n-1-index]; 
       int tempColRightLast = a[n-1-index][n-1-index];
       int tempRowBottomLast = a[n-1-index][index]; 
       int tempColLeftLast = a[index][index];

       int temp, temp2;

       temp = tempColLeftLast; 

       for (int k = index + 1; k < n-index; k++) {
           temp2 = a[index][k];
           a[index][k] = temp;
           temp = temp2;
       }

       temp = tempRowTopLast; 
       for (int k = index + 1; k < n-index; k++) {
           temp2 = a[k][n-1-index];
           a[k][n-1-index] = temp; 
           temp = temp2; 
       }

       temp = tempColRightLast; 
       for (int k = n-2-index; k >=index; k--) {
           temp2 = a[n-1-index][k];
           a[n-1-index][k] = temp; 
           temp = temp2; 
       }

       temp = tempRowBottomLast;
       for (int k = n-2-index; k >=index; k--) {
           temp2 = a[k][index];
           a[k][index] = temp;
           temp = temp2;
       } 

       shiftArray(a, index+1, n);

    }

    public static void main(String[] args) {
        int a[][] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

        shiftArray(a, 0, 3);
        System.out.println("Rotated array...");

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(a[i][j] + ",");
            }
            System.out.println();
       }
    }
}

答案 4 :(得分:0)

for i in range (0,len(farm) - 2):
   if any(farm[i] == farm[i+1] == farm[i+2] == target for target in lookup):
       print(i)    

答案 5 :(得分:0)

顺时针旋转90度。 Python3中的O(n ^ 2)时间和O(1)内存:

CollectionReference col1 = Firestore.instance.collection('service');
final snapshots = col1.snapshots().map((snapshot) => snapshot.documents.where((doc) => doc["title"] == "Ac replaciment" || doc["title"] == "Oil Service"));
return (await snapshots.first).toList();