行列の回転
問題
N*Nの行列を90度回転させる
考え方
あまりたくさんのメモリを使いたくないので、1つの値だけを保持して回転させたい。
回転させると(i, j)
-> (j, N-i)
に移る。移った先を考えると、
(j, N-i)
->(N-i, N-j)
(N-i, N-j)
->(N-j, i)
(N-j, i)
->(i, j)
まずは4 * 4の行列から考えてみる。
回転させると(0, 0)
-> (0, 3)
に移る。この点を循環させて、次に(0, 1)
, (0,2)
と行うが、(0, 3)
までやるとすでに回転させたものがあることに気づく。
つまり、列はNまでは行わない。
また、次の行に進もうとすると、初めの列はすでに回転したものであるから、その次の列から行う必要がある。
以上のことに注意すると、行i
に対して、列はi -> N/2
まで回転を行う。
また、4点を回転させるときに、どれか1つだけメモリに入れておいて、回転させる。
計算量
全ての点をみる必要があるので、時間計算量はO(N)
である。追加で必要な空間計算量は1
で済む。
コード例
#include<iostream> using namespace std; void rotate(int N, int **matrix){ int i, j, start, end; int temp; i = 0; end = N; for(start=0; start<N/2; start++){ // 列の動く量 end--; for(j=start; j<end; j++){ temp = matrix[N-1-j][i]; matrix[N-1-j][i] = matrix[N-1-i][N-1-j]; matrix[N-1-i][N-1-j] = matrix[j][N-1-i]; matrix[j][N-1-i] = matrix[i][j]; matrix[i][j] = temp; } i++;//行を次に進める } } int main(void){ int i, j, N; N = 5; int **matrix = (int**)malloc(N*sizeof(int*)); matrix[0] = (int*)malloc(N*N*sizeof(int)); for(i=0; i<N; i++){ matrix[i] = matrix[0] + i*N; } for(i=0; i<N; i++){ for(j=0; j<N; j++){ matrix[i][j] = i+j; } } cout << "元の行列" << endl; for(i=0; i<N; i++){ for(j=0; j<N; j++){ cout << matrix[i][j] << " "; } cout << endl; } rotate(N, matrix); cout << "回転させた行列" << endl; for(i=0; i<N; i++){ for(j=0; j<N; j++){ cout << matrix[i][j] << " "; } cout << endl; } return 0; }