Rotate a Matrix by Any Multiple of 90 Degrees, In Place Where the Shape Allows
Company: Oracle
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Rotate a 2-D integer matrix by a given angle. The core case is a square `n × n` matrix turned 90 degrees clockwise in place: rearrange the values inside the input matrix itself, using only constant extra space, instead of copying them into a second matrix. Your function must also handle two generalizations: any multiple of 90 degrees in either direction, and rectangular `m × n` matrices.
### Function Signature
```python
def rotate_matrix(matrix: list[list[int]], degrees: int) -> list[list[int]]:
```
### Rules
- `matrix` is a list of `m` rows, each a list of `n` integers.
- `degrees` is a multiple of 90. A positive value rotates clockwise, a negative value rotates counter-clockwise, and `0` leaves the matrix unchanged. Angles wrap around every full turn, so rotating by `degrees` gives the same result as rotating by `degrees - 360` or `degrees + 360`.
- One clockwise quarter turn moves the value at row `r`, column `c` of an `m × n` matrix to row `c`, column `m - 1 - r` of an `n × m` result. A counter-clockwise quarter turn is the inverse of that move, and a half turn is two quarter turns in the same direction.
- When the result has the same shape as the input (every square matrix, and any matrix turned by a multiple of 180 degrees), rotate in place: move the values within `matrix` using `O(1)` extra space, without allocating a second matrix, and return `matrix` itself.
- When the result has a different shape (a matrix with `m != n` turned by an odd number of quarter turns), return a new `n × m` matrix.
- Return the rotated matrix as a list of rows.
### Constraints
- `1 <= m <= 200` and `1 <= n <= 200`
- `-10^9 <= matrix[r][c] <= 10^9`; values may repeat.
- `-10^6 <= degrees <= 10^6` and `degrees % 90 == 0`
- Every input value fits in a 32-bit signed integer.
### Examples
**Example 1**
```text
Input: matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], degrees = 90
Output: [[7, 4, 1], [8, 5, 2], [9, 6, 3]]
```
The first column, read from bottom to top, becomes the first row. The matrix is square, so it is rotated in place and `matrix` itself is returned.
**Example 2**
```text
Input: matrix = [[1, 2, 3], [4, 5, 6]], degrees = -90
Output: [[3, 6], [2, 5], [1, 4]]
```
A counter-clockwise quarter turn of a 2 × 3 matrix produces a 3 × 2 matrix: the last column, read from top to bottom, becomes the first row.
**Example 3**
```text
Input: matrix = [[1, 2], [3, 4], [5, 6]], degrees = -540
Output: [[6, 5], [4, 3], [2, 1]]
```
`-540` wraps around to a half turn, because `-540 + 720 = 180`. The shape stays 3 × 2, so the rotation is done in place.
Overview: Rotate a 2-D integer matrix by any multiple of 90 degrees, clockwise or counter-clockwise, and return the rotated grid. Square matrices and half turns must be rotated in place with constant extra space, while a quarter turn of a rectangular matrix produces a new matrix with swapped dimensions. It tests index mapping, angle normalization and in-place element movement.