Given a matrix of order m*n and a value k, the task is to rotate each ring of the matrix anticlockwise by k.
Examples:
Input : k = 3, mat[][] =
{{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}}
Output: mat[][] =
{{4, 8, 12, 16},
{3, 10, 6, 15},
{2, 11, 7, 14},
{1, 5, 9, 13}}Input : k = 2, mat[][] =
{{1, 2, 3, 4},
{10, 11, 12, 5},
{9, 8, 7, 6}}
Output: mat[][] =
{{3, 4, 5, 6},
{2, 11, 12, 7},
{1, 10, 9, 8}}
Naive Solution - O(k*m*n) Time and O(1) Space
We simply use the solution of rotate by one and call it in a loop.
#include <bits/stdc++.h>
using namespace std;
// Used inside rotateMatrixKTimes()
void rotateMatrix(vector<vector<int>>& mat);
// Function to rotate the matrix k times
void rotateMatrixKTimes(vector<vector<int>>& mat, int k) {
for (int i = 0; i < k; i++) {
rotateMatrix(mat);
}
}
// Function to rotate a matrix counterclockwise
void rotateMatrix(vector<vector<int>>& mat) {
int m = mat.size();
int n = mat[0].size();
int row = 0, col = 0;
int prev, curr;
// Rotate the matrix in layers
while (row < m && col < n) {
if (row + 1 == m || col + 1 == n)
break;
// Store the first element of the next column
prev = mat[row][col + 1];
// Move elements of the first column
for (int i = row; i < m; i++) {
curr = mat[i][col];
mat[i][col] = prev;
prev = curr;
}
col++;
// Move elements of the last row
for (int i = col; i < n; i++) {
curr = mat[m - 1][i];
mat[m - 1][i] = prev;
prev = curr;
}
m--;
// Move elements of the last column
if (col < n) {
for (int i = m - 1; i >= row; i--) {
curr = mat[i][n - 1];
mat[i][n - 1] = prev;
prev = curr;
}
}
n--;
// Move elements of the first row
if (row < m) {
for (int i = n - 1; i >= col; i--) {
curr = mat[row][i];
mat[row][i] = prev;
prev = curr;
}
}
row++;
}
}
int main() {
vector<vector<int>> mat = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}
};
int k = 2; // Rotate the matrix 2 times
rotateMatrixKTimes(mat, k);
// Print the rotated matrix
for (auto& r : mat) {
for (int val : r)
cout << val << " ";
cout << endl;
}
return 0;
}
Efficient Solution - O(m*n) Time and O(m*n) Space
The idea is to traverse matrix in spiral form. Here is the algorithm to solve this problem :
- Make an auxiliary array temp[] of size m*n.
- Start traversing matrix in spiral form and store elements of current ring in temp[] array. While storing the elements in temp, keep track of starting and ending positions of current ring.
- For every ring that is being stored in temp[], rotate that subarray temp[]
- Repeat this process for each ring of matrix.
- In last traverse matrix again spirally and copy elements of temp[] array to matrix..
#include<bits/stdc++.h>
using namespace std;
// Fills temp array into mat using spiral order traversal.
// Used inside the main function spiralRotate()
void fillSpiral(vector<vector<int>>& mat, vector<int>& temp);
void spiralRotate(vector<vector<int>>& mat, int k) {
int m = mat.size();
int n = mat[0].size();
// Temporary array to store elements in the spiral order
vector<int> temp;
int s = 0, l = 0;
while (s < m && l < n) {
// Record the start position of the current ring
int start = temp.size();
// copy the first row from the remaining rows
for (int i = l; i < n; ++i)
temp.push_back(mat[s][i]);
s++;
// copy the last column from the remaining columns
for (int i = s; i < m; ++i)
temp.push_back(mat[i][n - 1]);
n--;
// copy the last row from the remaining rows
if (s < m) {
for (int i = n - 1; i >= l; --i)
temp.push_back(mat[m - 1][i]);
m--;
}
// copy the first column from the remaining columns
if (l < n) {
for (int i = m - 1; i >= s; --i)
temp.push_back(mat[i][l]);
l++;
}
int ringSize = temp.size() - start;
// Adjust k to rotate only within the current ring
int kNew = k % ringSize;
// Rotate the current ring using the reversal algorithm
reverse(temp.begin() + start, temp.begin() + start + kNew);
reverse(temp.begin() + start + kNew, temp.begin() + temp.size());
reverse(temp.begin() + start, temp.begin() + temp.size());
}
// Fill the matrix back using the temp array
fillSpiral(mat, temp);
}
// Fills temp array into mat using spiral order traversal.
void fillSpiral(vector<vector<int>>& mat, vector<int>& temp) {
int m = mat.size();
int n = mat[0].size();
int k = 0, l = 0;
int tIdx = 0; // Index in temp array
while (k < m && l < n) {
// first row from the remaining rows
for (int i = l; i < n; ++i)
mat[k][i] = temp[tIdx++];
k++;
// last column from the remaining columns
for (int i = k; i < m; ++i)
mat[i][n - 1] = temp[tIdx++];
n--;
// last row from the remaining rows
if (k < m) {
for (int i = n - 1; i >= l; --i)
mat[m - 1][i] = temp[tIdx++];
m--;
}
// first column from the remaining columns
if (l < n) {
for (int i = m - 1; i >= k; --i)
mat[i][l] = temp[tIdx++];
l++;
}
}
}
int main() {
int k = 5;
vector<vector<int>> mat = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}
};
spiralRotate(mat, k);
for (auto& row : mat) {
for (int val : row)
cout << val << " ";
cout << endl;
}
return 0;
}
import java.util.*;
public class Main {
static final int MAX = 100;
// Fills temp array into mat[][] using spiral order
// traversal.
static void FillSpiral(int[][] mat, int m, int n,
int[] temp)
{
int k = 0, l = 0;
int tIdx = 0; // Index in temp array
while (k < m && l < n) {
// first row from the remaining rows
for (int i = l; i < n; ++i) {
mat[k][i] = temp[tIdx++];
}
k++;
// last column from the remaining columns
for (int i = k; i < m; ++i) {
mat[i][n - 1] = temp[tIdx++];
}
n--;
// last row from the remaining rows
if (k < m) {
for (int i = n - 1; i >= l; --i) {
mat[m - 1][i] = temp[tIdx++];
}
m--;
}
// first column from the remaining columns
if (l < n) {
for (int i = m - 1; i >= k; --i) {
mat[i][l] = temp[tIdx++];
}
l++;
}
}
}
static void SpiralRotate(int[][] mat, int M, int N,
int k)
{
// Create a temporary array to store the result
int[] temp = new int[M * N];
int m = M, n = N, s = 0, l = 0;
// Initialize end position of current ring
int tIdx = 0;
int start = 0;
while (s < m && l < n) {
int end = start;
// copy the first row from the remaining rows
for (int i = l; i < n; ++i) {
temp[tIdx++] = mat[s][i];
end++;
}
s++;
// copy the last column from the remaining
// columns
for (int i = s; i < m; ++i) {
temp[tIdx++] = mat[i][n - 1];
end++;
}
n--;
// copy the last row from the remaining rows
if (s < m) {
for (int i = n - 1; i >= l; --i) {
temp[tIdx++] = mat[m - 1][i];
end++;
}
m--;
}
if (l < n) {
for (int i = m - 1; i >= s; --i) {
temp[tIdx++] = mat[i][l];
end++;
}
l++;
}
// if elements in current ring greater than k
// then rotate elements of current ring
if (end - start > k) {
// Rotate current ring using reversal
// algorithm for rotation
reverseArray(temp, start, start + k - 1);
reverseArray(temp, start + k, end - 1);
reverseArray(temp, start, end - 1);
start = end;
}
}
// Fill temp array in original matrix.
FillSpiral(mat, M, N, temp);
}
// Reverse Array
static void reverseArray(int[] arr, int start, int end)
{
while (start < end) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
// Driver code
public static void main(String[] args)
{
int M = 4, N = 4, k = 3;
int[][] mat = { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
SpiralRotate(mat, M, N, k);
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
System.out.print(mat[i][j] + " ");
}
System.out.println();
}
}
}
# Python program to rotate individual rings by k in
# spiral order traversal.
MAX = 100
# Fills temp array into mat[][] using spiral order
# traversal.
def fillSpiral(mat, m, n, temp):
i, k, l = 0, 0, 0
tIdx = 0 # Index in temp array
while k < m and l < n:
# first row from the remaining rows
for i in range(l, n):
mat[k][i] = temp[tIdx]
tIdx += 1
k += 1
# last column from the remaining columns
for i in range(k, m):
mat[i][n-1] = temp[tIdx]
tIdx += 1
n -= 1
# last row from the remaining rows
if k < m:
for i in range(n-1, l-1, -1):
mat[m-1][i] = temp[tIdx]
tIdx += 1
m -= 1
# first column from the remaining columns
if l < n:
for i in range(m-1, k-1, -1):
mat[i][l] = temp[tIdx]
tIdx += 1
l += 1
# Rotates the individual rings in spiral order
def spiralRotate(mat, M, N, k):
# Create a temporary array to store the result
temp = [0] * (M*N)
m, n, s, l = M, N, 0, 0
start = 0 # Start position of current ring
tIdx = 0 # Index in temp
while s < m and l < n:
# Initialize end position of current ring
end = start
# copy the first row from the remaining rows
for i in range(l, n):
temp[tIdx] = mat[s][i]
tIdx += 1
end += 1
s += 1
# copy the last column from the remaining columns
for i in range(s, m):
temp[tIdx] = mat[i][n-1]
tIdx += 1
end += 1
n -= 1
# copy the last row from the remaining rows
if s < m:
for i in range(n-1, l-1, -1):
temp[tIdx] = mat[m-1][i]
tIdx += 1
end += 1
m -= 1
# copy the first column from the remaining columns
if l < n:
for i in range(m-1, s-1, -1):
temp[tIdx] = mat[i][l]
tIdx += 1
end += 1
l += 1
# if elements in current ring greater than k then rotate elements of current ring
if end-start > k:
# Rotate current ring using reversal algorithm for rotation
temp[start:start+k], temp[start+k:end] = reversed(temp[start:start+k]), reversed(temp[start+k:end])
temp[start:end] = reversed(temp[start:end])
# Reset start for next ring
start = end
# Fill temp array in original matrix.
fillSpiral(mat, M, N, temp)
# Driver program to run the case
if __name__ == "__main__":
M = 4
N = 4
k = 3
mat = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]]
spiralRotate(mat, M, N, k)
# print modified matrix
for i in range(M):
for j in range(N):
print(mat[i][j], end=" ")
print()
# This code is contributed by Prince Kumar
// C# program to rotate individual rings by k in
// spiral order traversal.
using System;
class Program
{
const int MAX = 100;
// Fills temp array into mat[][] using spiral order
// traversal.
static void FillSpiral(int[,] mat, int m, int n, int[] temp)
{
int k = 0, l = 0;
int tIdx = 0;// Index in temp array
while (k < m && l < n)
{
/* first row from the remaining rows */
for (int i = l; i < n; ++i)
{
mat[k, i] = temp[tIdx++];
}
k++;
/* last column from the remaining columns */
for (int i = k; i < m; ++i)
{
mat[i, n - 1] = temp[tIdx++];
}
n--;
/* last row from the remaining rows */
if (k < m)
{
for (int i = n - 1; i >= l; --i)
{
mat[m - 1, i] = temp[tIdx++];
}
m--;
}
/* first column from the remaining columns */
if (l < n)
{
for (int i = m - 1; i >= k; --i)
{
mat[i, l] = temp[tIdx++];
}
l++;
}
}
}
static void SpiralRotate(int[,] mat, int M, int N, int k)
{
// Create a temporary array to store the result
int[] temp = new int[M * N];
int m = M, n = N, s = 0, l = 0;
// Initialize end position of current ring
int tIdx = 0;
int start = 0;
while (s < m && l < n)
{
int end = start;
// copy the first row from the remaining rows
for (int i = l; i < n; ++i)
{
temp[tIdx++] = mat[s, i];
end++;
}
s++;
// copy the last column from the remaining columns
for (int i = s; i < m; ++i)
{
temp[tIdx++] = mat[i, n - 1];
end++;
}
n--;
// copy the last row from the remaining rows
if (s < m)
{
for (int i = n - 1; i >= l; --i)
{
temp[tIdx++] = mat[m - 1, i];
end++;
}
m--;
}
if (l < n)
{
for (int i = m - 1; i >= s; --i)
{
temp[tIdx++] = mat[i, l];
end++;
}
l++;
}
// if elements in current ring greater than
// k then rotate elements of current ring
if (end - start > k)
{
// Rotate current ring using reversal
// algorithm for rotation
Array.Reverse(temp, start, k);
Array.Reverse(temp, start + k, end - start - k);
Array.Reverse(temp, start, end - start);
start = end;
}
}
// Fill temp array in original matrix.
FillSpiral(mat, M, N, temp);
}
// Driver program to run the case
static void Main(string[] args)
{
// Your C++ Code
int M = 4, N = 4, k = 3;
int[,] mat = { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
SpiralRotate(mat, M, N, k);
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
Console.Write(mat[i, j] + " ");
}
Console.WriteLine();
}
}
}
// JavaScript program to rotate individual rings by k in
// spiral order traversal.
const MAX = 100;
// Fills temp array into mat[][] using spiral order traversal.
function fillSpiral(mat, m, n, temp) {
let i = 0,
k = 0,
l = 0;
let tIdx = 0; // Index in temp array
while (k < m && l < n) {
// first row from the remaining rows
for (i = l; i < n; i++) {
mat[k][i] = temp[tIdx];
tIdx++;
}
k++;
// last column from the remaining columns
for (i = k; i < m; i++) {
mat[i][n - 1] = temp[tIdx];
tIdx++;
}
n--;
// last row from the remaining rows
if (k < m) {
for (i = n - 1; i >= l; i--) {
mat[m - 1][i] = temp[tIdx];
tIdx++;
}
m--;
}
// first column from the remaining columns
if (l < n) {
for (i = m - 1; i >= k; i--) {
mat[i][l] = temp[tIdx];
tIdx++;
}
l++;
}
}
}
// Rotates the individual rings in spiral order
function spiralRotate(mat, M, N, k) {
// Create a temporary array to store the result
const temp = new Array(M * N).fill(0);
let m = M,
n = N,
s = 0,
l = 0;
let start = 0; // Start position of current ring
let tIdx = 0; // Index in temp
while (s < m && l < n) {
// Initialize end position of current ring
let end = start;
// copy the first row from the remaining rows
for (let i = l; i < n; i++) {
temp[tIdx] = mat[s][i];
tIdx++;
end++;
}
s++;
// copy the last column from the remaining columns
for (let i = s; i < m; i++) {
temp[tIdx] = mat[i][n - 1];
tIdx++;
end++;
}
n--;
// copy the last row from the remaining rows
if (s < m) {
for (let i = n - 1; i >= l; i--) {
temp[tIdx] = mat[m - 1][i];
tIdx++;
end++;
}
m--;
}
// copy the first column from the remaining columns
if (l < n) {
for (let i = m - 1; i >= s; i--) {
temp[tIdx] = mat[i][l];
tIdx++;
end++;
}
l++;
}
// if elements in current ring greater than k then rotate elements of current ring
if (end - start > k) {
// Rotate current ring using reversal algorithm for rotation
temp.splice(start, k, ...temp.slice(start, start + k).reverse());
temp.splice(start + k, end - start - k, ...temp.slice(start + k, end).reverse());
temp.splice(start, end - start, ...temp.slice(start, end).reverse());
start = end;
}
}
fillSpiral(mat, M, N, temp);
}
const M = 4;
const N = 4;
const k = 3;
const mat = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
];
spiralRotate(mat, M, N, k);
// print modified matrix
for (let i = 0; i < M; i++) {
for (let j = 0; j < N; j++) {
process.stdout.write(mat[i][j] + " ");
}
console.log();
}
// This code is generated by chetan bargal
Output
4 8 12 16 3 10 6 15 2 11 7 14 1 5 9 13