This problem took me quite a while, but if you have the right approach, it is very simple.
Note that this only works for a square matrix . The rectangle will require you to use a different algorithm (transpose and switch). If you want to do this in place, you may need to temporarily resize the array.
Simplification of the problem
Consider the following matrix:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Turn 90 degrees and look only at the corners (numbers 1, 4, 16 and 13). If you have problems with visualization, help yourself with the recording after that.
Now consider the following:
1 - - 2 - - - - - - - - 4 - - 3
Turn it 90 degrees and pay attention to how the numbers rotate in a circular manner: 2 becomes 1, 3 becomes 2, 4 becomes 3, 1 becomes 4.
Rotating corners
To rotate the corners, you need to define all the angles in terms of the first corner:
- 1st angle will be
(i, j) - The second corner will be
(SIZE - j, i) - The third corner will be
(SIZE - i, SIZE - j) - The fourth corner will be
(j, SIZE - i)
Note that arrays are based on 0, so SIZE should also be based on 0. (this means you will need to subtract 1).
Now that you understand the idea of ββrotating angles, we will expand the idea of ββ"rotating angles" to "rotating quadrants." The same principle holds.
The code
You will need to make sure that the number is not overwritten. So you will need to rotate 4 numbers at the same time.
#include <algorithm> #include <numeric> #include <vector> using std::iota; using std::swap; using std::vector; // Rotates 4 numbers. // eg: 1, 2, 3, 4 becomes 4, 1, 2, 3 // int& means numbers are passed by reference, not copy. void rotate4(int &a, int &b, int &c, int &d) { swap(a, b); swap(b, c); swap(c, d); } void rotateMatrix(vector<vector<int>>& m) { int n = m.size(); // NOTE: i and j from 0 to n/2 is a quadrant for (int i = 0; i < n/2; i++) { // NOTE : here + 1 is added to make it work when n is odd for (int j = 0; j < (n + 1)/2; j++) { int r_i = (n - 1) - i; int r_j = (n - 1) - j; rotate4( m [i] [j], m [r_j] [i], m [r_i] [r_j], m [j] [r_i] ); } } } void fillMatrix(vector<vector<int>>& m) { int offset = 0; for (auto &i : m) { iota(i.begin(), i.end(), offset); offset += i.size(); } } // Usage: const int size = 8; vector<vector<int>> matrix (size, vector<int>(size)); fillMatrix(matrix); rotateMatrix(matrix);
Print
To print a matrix that you can use:
#include <algorithm> #include <iostream> #include <iterator> using std::copy; using std::cout; using std::ostream; using std::ostream_iterator; using std::vector; ostream& operator<<(ostream& os, vector<vector<int>>& m) { for (auto const &i : m) { copy(i.begin(), i.end(), ostream_iterator<int>(os, " ")); os << "\n"; } return os; } // Usage cout << matrix;