Add square matrix rotation in-place algorithm.

This commit is contained in:
Oleksii Trekhleb 2018-07-06 08:15:56 +03:00
parent 17ad4dc4d1
commit 75133592bb
4 changed files with 178 additions and 0 deletions

View File

@ -116,6 +116,7 @@ a set of rules that precisely define a sequence of operations.
* `B` [Tower of Hanoi](src/algorithms/uncategorized/hanoi-tower) * `B` [Tower of Hanoi](src/algorithms/uncategorized/hanoi-tower)
* `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens) * `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens)
* `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour) * `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour)
* `B` [Square Matrix Rotation](src/algorithms/uncategorized/square-matrix-rotation) - in-place algorithm
### Algorithms by Paradigm ### Algorithms by Paradigm

View File

@ -0,0 +1,90 @@
# Square Matrix In-Place Rotation
## The Problem
You are given an `n x n` 2D matrix (representing an image).
Rotate the matrix by `90` degrees (clockwise).
**Note**
You have to rotate the image **in-place**, which means you
have to modify the input 2D matrix directly. **DO NOT** allocate
another 2D matrix and do the rotation.
## Examples
**Example #1**
Given input matrix:
```
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
```
Rotate the input matrix in-place such that it becomes:
```
[
[7, 4, 1],
[8, 5, 2],
[9, 6, 3],
]
```
**Example #2**
Given input matrix:
```
[
[5, 1, 9, 11],
[2, 4, 8, 10],
[13, 3, 6, 7],
[15, 14, 12, 16],
]
```
Rotate the input matrix in-place such that it becomes:
```
[
[15, 13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7, 10, 11],
]
```
## Algorithm
We would need to do two reflections of the matrix:
- reflect vertically
- reflect diagonally from bottom-left to top-right
Or we also could Furthermore, you can reflect diagonally
top-left/bottom-right and reflect horizontally.
A common question is how do you even figure out what kind
of reflections to do? Simply rip a square piece of paper,
write a random word on it so you know its rotation. Then,
flip the square piece of paper around until you figure out
how to come to the solution.
Here is an example of how first line may be rotated using
diagonal top-right/bottom-left rotation along with horizontal
rotation.
```
A B C A - - . . A
/ / --> B - - --> . . B
/ . . C - - . . C
```
## References
- [LeetCode](https://leetcode.com/problems/rotate-image/description/)

View File

@ -0,0 +1,59 @@
import squareMatrixRotation from '../squareMatrixRotation';
describe('squareMatrixRotation', () => {
it('should rotate matrix #0 in-place', () => {
const matrix = [[1]];
const rotatedMatrix = [[1]];
expect(squareMatrixRotation(matrix)).toEqual(rotatedMatrix);
});
it('should rotate matrix #1 in-place', () => {
const matrix = [
[1, 2],
[3, 4],
];
const rotatedMatrix = [
[3, 1],
[4, 2],
];
expect(squareMatrixRotation(matrix)).toEqual(rotatedMatrix);
});
it('should rotate matrix #2 in-place', () => {
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const rotatedMatrix = [
[7, 4, 1],
[8, 5, 2],
[9, 6, 3],
];
expect(squareMatrixRotation(matrix)).toEqual(rotatedMatrix);
});
it('should rotate matrix #3 in-place', () => {
const matrix = [
[5, 1, 9, 11],
[2, 4, 8, 10],
[13, 3, 6, 7],
[15, 14, 12, 16],
];
const rotatedMatrix = [
[15, 13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7, 10, 11],
];
expect(squareMatrixRotation(matrix)).toEqual(rotatedMatrix);
});
});

View File

@ -0,0 +1,28 @@
/**
* @param {*[][]} originalMatrix
* @return {*[][]}
*/
export default function squareMatrixRotation(originalMatrix) {
const matrix = originalMatrix.slice();
// Do top-right/bottom-left diagonal reflection of the matrix.
for (let rowIndex = 0; rowIndex < matrix.length; rowIndex += 1) {
for (let columnIndex = rowIndex + 1; columnIndex < matrix.length; columnIndex += 1) {
const tmp = matrix[columnIndex][rowIndex];
matrix[columnIndex][rowIndex] = matrix[rowIndex][columnIndex];
matrix[rowIndex][columnIndex] = tmp;
}
}
// Do horizontal reflection of the matrix.
for (let rowIndex = 0; rowIndex < matrix.length; rowIndex += 1) {
for (let columnIndex = 0; columnIndex < matrix.length / 2; columnIndex += 1) {
const mirrorColumnIndex = matrix.length - columnIndex - 1;
const tmp = matrix[rowIndex][mirrorColumnIndex];
matrix[rowIndex][mirrorColumnIndex] = matrix[rowIndex][columnIndex];
matrix[rowIndex][columnIndex] = tmp;
}
}
return matrix;
}