Inplace (Fixed space) M x N size matrix transpose
Last Updated :
23 Jul, 2025
Given an M x N matrix, transpose the matrix without auxiliary memory.It is easy to transpose matrix using an auxiliary array. If the matrix is symmetric in size, we can transpose the matrix inplace by mirroring the 2D array across it's diagonal (try yourself). How to transpose an arbitrary size matrix inplace? See the following matrix,
a b c a d g j
d e f ==> b e h k
g h i c f i l
j k l
As per 2D numbering in C/C++, corresponding location mapping looks like,
Org element New
0 a 0
1 b 4
2 c 8
3 d 1
4 e 5
5 f 9
6 g 2
7 h 6
8 i 10
9 j 3
10 k 7
11 l 11
Note that the first and last elements stay in their original location. We can easily see the transformation forms few permutation cycles.
- 1->4->5->9->3->1 - Total 5 elements form the cycle
- 2->8->10->7->6->2 - Another 5 elements form the cycle
- 0 - Self cycle
- 11 - Self cycle
From the above example, we can easily devise an algorithm to move the elements along these cycles. How can we generate permutation cycles? Number of elements in both the matrices are constant, given by N = R * C, where R is row count and C is column count. An element at location ol (old location in R x C matrix), moved to nl (new location in C x R matrix). We need to establish relation between ol, nl, R and C. Assume ol = A[or][oc]. In C/C++ we can calculate the element address as,
ol = or x C + oc (ignore base reference for simplicity)
It is to be moved to new location nl in the transposed matrix, say nl = A[nr][nc], or in C/C++ terms
nl = nr x R + nc (R - column count, C is row count as the matrix is transposed)
Observe, nr = oc and nc = or, so replacing these for nl,
nl = oc x R + or -----> [eq 1]
after solving for relation between ol and nl, we get
ol = or x C + oc
ol x R = or x C x R + oc x R
= or x N + oc x R (from the fact R * C = N)
= or x N + (nl - or) --- from [eq 1]
= or x (N-1) + nl
OR,
nl = ol x R - or x (N-1)
Note that the values of nl and ol never go beyond N-1, so considering modulo division on both the sides by (N-1), we get the following based on properties of congruence,
nl mod (N-1) = (ol x R - or x (N-1)) mod (N-1)
= (ol x R) mod (N-1) - or x (N-1) mod(N-1)
= ol x R mod (N-1), since second term evaluates to zero
nl = (ol x R) mod (N-1), since nl is always less than N-1
A curious reader might have observed the significance of above relation. Every location is scaled by a factor of R (row size). It is obvious from the matrix that every location is displaced by scaled factor of R. The actual multiplier depends on congruence class of (N-1), i.e. the multiplier can be both -ve and +ve value of the congruent class.Hence every location transformation is simple modulo division. These modulo divisions form cyclic permutations. We need some book keeping information to keep track of already moved elements. Here is code for inplace matrix transformation,
Implementation:
C++
// C++ program for in-place matrix transpose
#include <bits/stdc++.h>
#define HASH_SIZE 128
using namespace std;
// A utility function to print a 2D array
// of size nr x nc and base address A
void Print2DArray(int *A, int nr, int nc)
{
for(int r = 0; r < nr; r++)
{
for(int c = 0; c < nc; c++)
{
cout<<setw(4)<<*(A + r*nc + c);
}
cout<<endl;
}
cout<<endl;
}
// Non-square matrix transpose of
// matrix of size r x c and base address A
void MatrixInplaceTranspose(int *A, int r, int c)
{
int size = r*c - 1;
int t; // holds element to be replaced,
// eventually becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
bitset<HASH_SIZE> b; // hash to mark moved elements
b.reset();
b[0] = b[size] = 1;
i = 1; // Note that A[0] and A[size-1] won't move
while (i < size)
{
cycleBegin = i;
t = A[i];
do
{
// Input matrix [r x c]
// Output matrix [c x r]
// i_new = (i*r)%(N-1)
next = (i*r)%size;
swap(A[next], t);
b[i] = 1;
i = next;
}
while (i != cycleBegin);
// Get Next Move (what about querying random location?)
for (i = 1; i < size && b[i]; i++)
;
cout << endl;
}
}
// Driver program to test above function
int main()
{
int r = 5, c = 6;
int size = r*c;
int *A = new int[size];
for(int i = 0; i < size; i++)
A[i] = i+1;
Print2DArray(A, r, c);
MatrixInplaceTranspose(A, r, c);
Print2DArray(A, c, r);
delete[] A;
return 0;
}
// This code is contributed by rrrtnx.
C
// Program for in-place matrix transpose
#include <stdio.h>
#include <iostream>
#include <bitset>
#define HASH_SIZE 128
using namespace std;
// A utility function to print a 2D array of size nr x nc and base address A
void Print2DArray(int *A, int nr, int nc)
{
for(int r = 0; r < nr; r++)
{
for(int c = 0; c < nc; c++)
printf("%4d", *(A + r*nc + c));
printf("\n");
}
printf("\n\n");
}
// Non-square matrix transpose of matrix of size r x c and base address A
void MatrixInplaceTranspose(int *A, int r, int c)
{
int size = r*c - 1;
int t; // holds element to be replaced, eventually becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
bitset<HASH_SIZE> b; // hash to mark moved elements
b.reset();
b[0] = b[size] = 1;
i = 1; // Note that A[0] and A[size-1] won't move
while (i < size)
{
cycleBegin = i;
t = A[i];
do
{
// Input matrix [r x c]
// Output matrix [c x r]
// i_new = (i*r)%(N-1)
next = (i*r)%size;
swap(A[next], t);
b[i] = 1;
i = next;
}
while (i != cycleBegin);
// Get Next Move (what about querying random location?)
for (i = 1; i < size && b[i]; i++)
;
cout << endl;
}
}
// Driver program to test above function
int main(void)
{
int r = 5, c = 6;
int size = r*c;
int *A = new int[size];
for(int i = 0; i < size; i++)
A[i] = i+1;
Print2DArray(A, r, c);
MatrixInplaceTranspose(A, r, c);
Print2DArray(A, c, r);
delete[] A;
return 0;
}
Java
// Java program for in-place matrix transpose
import java.util.*;
class gfg {
static int HASH_SIZE = 128;
// A utility function to pr a 2D array
// of size nr x nc and base address A
static void Pr2DArray(int[] A, int nr, int nc)
{
for (int r = 0; r < nr; r++) {
for (int c = 0; c < nc; c++) {
System.out.print(String.format(
"%1$" + 4 + "s", (A[r * nc + c] + "")));
}
System.out.println();
}
System.out.println();
}
// Non-square matrix transpose of
// matrix of size r x c and base address A
static int[] MatrixInplaceTranspose(int[] A, int r,
int c)
{
int size = r * c - 1;
int t; // holds element to be replaced,
// eventually becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
int b = 1; // hash to mark moved elements
b |= (1 << size);
i = 1; // Note that A[0] and A[size-1] won't move
while (i < size) {
cycleBegin = i;
t = A[i];
do {
// Input matrix [r x c]
// Output matrix
// i_new = (i*r)%(N-1)
next = (i * r) % size;
int temp = A[next];
A[next] = t;
t = temp;
b |= (1 << i);
i = next;
} while (i != cycleBegin);
// Get Next Move (what about querying random
// location?)
for (i = 1; i < size && ((b & (1 << i)) != 0);
i++)
;
System.out.println();
}
return A;
}
// Driver program to test above function
public static void main(String[] args)
{
int r = 5, c = 6;
int size = r * c;
int[] A = new int[size];
for (int i = 0; i < size; i++)
A[i] = i + 1;
Pr2DArray(A, r, c);
A = MatrixInplaceTranspose(A, r, c);
Pr2DArray(A, c, r);
}
}
// This code is contributed by karandeep1234
Python3
# Python3 program for in-place matrix transpose
HASH_SIZE = 128
# A utility function to pr a 2D array
# of size nr x nc and base address A
def Pr2DArray( A, nr, nc):
for r in range(nr):
for c in range(nc):
print('{0: >4}'.format(str(A[r * nc + c])), end = "")
print()
print()
# Non-square matrix transpose of
# matrix of size r x c and base address A
def MatrixInplaceTranspose( A, r, c):
size = r * c - 1;
b = 1; # hash to mark moved elements
b |= (1 << size);
i = 1; # Note that A[0] and A[size-1] won't move
while (i < size):
cycleBegin = i;
t = A[i];
while True:
# Input matrix [r x c]
# Output matrix [c x r]
# i_new = (i*r)%(N-1)
next1 = (i*r)%size;
temp = A[next1]
A[next1] = t
t = temp
b |= (1 << i)
i = next1;
if i == cycleBegin:
break
# Get next1 Move (what about querying random location?)
i = 1
while i < size and ( (b & (1 << i)) != 0):
i += 1
print()
return A
# Driver program to test above function
r = 5
c = 6;
size = r*c;
A = [i + 1 for i in range(size)]
Pr2DArray(A, r, c);
A = MatrixInplaceTranspose(A, r, c);
Pr2DArray(A, c, r);
# This code is contributed by phasing17.
C#
// C# program for in-place matrix transpose
using System;
using System.Collections.Generic;
class GFg
{
static int HASH_SIZE = 128;
// A utility function to pr a 2D array
// of size nr x nc and base address A
static void Pr2DArray(int[] A, int nr, int nc)
{
for(int r = 0; r < nr; r++)
{
for(int c = 0; c < nc; c++)
{
Console.Write(Convert.ToString(A[r * nc + c]).PadLeft(4));
}
Console.WriteLine();
}
Console.WriteLine();
}
// Non-square matrix transpose of
// matrix of size r x c and base address A
static int[] MatrixInplaceTranspose(int[] A, int r, int c)
{
int size = r * c - 1;
int t; // holds element to be replaced,
// eventually becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
int b = 1; // hash to mark moved elements
b |= (1 << size);
i = 1; // Note that A[0] and A[size-1] won't move
while (i < size)
{
cycleBegin = i;
t = A[i];
do
{
// Input matrix [r x c]
// Output matrix [c x r]
// i_new = (i*r)%(N-1)
next = (i*r)%size;
int temp = A[next];
A[next] = t;
t = temp;
b |= (1 << i);
i = next;
}
while (i != cycleBegin);
// Get Next Move (what about querying random location?)
for (i = 1; i < size && ( (b & (1 << i)) != 0); i++)
;
Console.WriteLine();
}
return A;
}
// Driver program to test above function
public static void Main(string[] args)
{
int r = 5, c = 6;
int size = r*c;
int[] A = new int[size];
for(int i = 0; i < size; i++)
A[i] = i+1;
Pr2DArray(A, r, c);
A = MatrixInplaceTranspose(A, r, c);
Pr2DArray(A, c, r);
}
}
// This code is contributed by phasing17.
JavaScript
// JS program for in-place matrix transpose
let HASH_SIZE = 128
// A utility function to pr a 2D array
// of size nr x nc and base address A
function Pr2DArray( A, nr, nc)
{
for(let r = 0; r < nr; r++)
{
for(let c = 0; c < nc; c++)
{
process.stdout.write((A[r * nc + c].toString()).padStart(4))
}
console.log()
}
console.log()
}
// Non-square matrix transpose of
// matrix of size r x c and base address A
function MatrixInplaceTranspose( A, r, c)
{
let size = r * c - 1;
let t; // holds element to be replaced,
// eventually becomes next element to move
let next; // location of 't' to be moved
let cycleBegin; // holds start of cycle
let i; // iterator
let b = 1; // hash to mark moved elements
b |= (1 << size);
i = 1; // Note that A[0] and A[size-1] won't move
while (i < size)
{
cycleBegin = i;
t = A[i];
do
{
// Input matrix [r x c]
// Output matrix [c x r]
// i_new = (i*r)%(N-1)
next = (i*r)%size;
let temp = A[next]
A[next] = t
t = temp
b |= (1 << i)
i = next;
}
while (i != cycleBegin);
// Get Next Move (what about querying random location?)
for (i = 1; i < size && ( (b & (1 << i)) != 0); i++)
;
console.log()
}
return A
}
// Driver program to test above function
let r = 5, c = 6;
let size = r*c;
let A = new Array(size);
for( i = 0; i < size; i++)
A[i] = i+1;
Pr2DArray(A, r, c);
A = MatrixInplaceTranspose(A, r, c);
Pr2DArray(A, c, r);
// This code is contributed by phasing17.
Output 1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
1 7 13 19 25
2 8 14 20 26
3 9 15 21 27
4 10 16 22 28
5 11 17 23 29
6 12 18 24 30
Time Complexity: O(R*C), here R & C are number number of Rows and Columns respectively.
Auxiliary Space : O(size of the bitset)
Extension: 17 - March - 2013 Some readers identified similarity between the matrix transpose and string transformation. Without much theory I am presenting the problem and solution. In given array of elements like [a1b2c3d4e5f6g7h8i9j1k2l3m4]. Convert it to [abcdefghijklm1234567891234]. The program should run inplace. What we need is an inplace transpose. Given below is code.
Implementation:
C++
#include <bits/stdc++.h>
#define HASH_SIZE 128
using namespace std;
typedef char data_t;
void Print2DArray(char A[], int nr, int nc) {
int size = nr*nc;
for(int i = 0; i < size; i++)
cout<<setw(4)<<*(A+i);
cout<<endl;
}
void MatrixTransposeInplaceArrangement(data_t A[], int r, int c) {
int size = r*c - 1;
data_t t; // holds element to be replaced, eventually becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
bitset<HASH_SIZE> b; // hash to mark moved elements
b.reset();
b[0] = b[size] = 1;
i = 1; // Note that A[0] and A[size-1] won't move
while( i < size ) {
cycleBegin = i;
t = A[i];
do {
// Input matrix [r x c]
// Output matrix [c x r]
// i_new = (i*r)%size
next = (i*r)%size;
swap(A[next], t);
b[i] = 1;
i = next;
} while( i != cycleBegin );
// Get Next Move (what about querying random location?)
for(i = 1; i < size && b[i]; i++)
;
cout << endl;
}
}
void Fill(data_t buf[], int size) {
// Fill abcd ...
for(int i = 0; i < size; i++)
buf[i] = 'a'+i;
// Fill 0123 ...
buf += size;
for(int i = 0; i < size; i++)
buf[i] = '0'+i;
}
void TestCase_01(void) {
int r = 2, c = 10;
int size = r*c;
data_t *A = new data_t[size];
Fill(A, c);
Print2DArray(A, r, c), cout << endl;
MatrixTransposeInplaceArrangement(A, r, c);
Print2DArray(A, c, r), cout << endl;
delete[] A;
}
int main() {
TestCase_01();
return 0;
}
// This code is contributed by rutvik_56.
C
#include <stdio.h>
#include <iostream>
#include <bitset>
#define HASH_SIZE 128
using namespace std;
typedef char data_t;
void Print2DArray(char A[], int nr, int nc) {
int size = nr*nc;
for(int i = 0; i < size; i++)
printf("%4c", *(A + i));
printf("\n");
}
void MatrixTransposeInplaceArrangement(data_t A[], int r, int c) {
int size = r*c - 1;
data_t t; // holds element to be replaced, eventually becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
bitset<HASH_SIZE> b; // hash to mark moved elements
b.reset();
b[0] = b[size] = 1;
i = 1; // Note that A[0] and A[size-1] won't move
while( i < size ) {
cycleBegin = i;
t = A[i];
do {
// Input matrix [r x c]
// Output matrix [c x r]
// i_new = (i*r)%size
next = (i*r)%size;
swap(A[next], t);
b[i] = 1;
i = next;
} while( i != cycleBegin );
// Get Next Move (what about querying random location?)
for(i = 1; i < size && b[i]; i++)
;
cout << endl;
}
}
void Fill(data_t buf[], int size) {
// Fill abcd ...
for(int i = 0; i < size; i++)
buf[i] = 'a'+i;
// Fill 0123 ...
buf += size;
for(int i = 0; i < size; i++)
buf[i] = '0'+i;
}
void TestCase_01(void) {
int r = 2, c = 10;
int size = r*c;
data_t *A = new data_t[size];
Fill(A, c);
Print2DArray(A, r, c), cout << endl;
MatrixTransposeInplaceArrangement(A, r, c);
Print2DArray(A, c, r), cout << endl;
delete[] A;
}
int main() {
TestCase_01();
return 0;
}
Java
import java.util.*;
class GFG {
static int HASH_SIZE = 128;
public static String padLeft(String s, int n)
{
return String.format("%" + n + "s", s);
}
static void Print2DArray(char[] A, int nr, int nc)
{
int size = nr * nc;
for (int i = 0; i < size; i++)
System.out.print(
padLeft(String.valueOf(A[i]), 4));
System.out.print("\n");
}
static void MatrixTransposeInplaceArrangement(char[] A,
int r,
int c)
{
int size = r * c - 1;
char t; // holds element to be replaced, eventually
// becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
int b = 1; // hash to mark moved elements
b |= (1 << size);
i = 1; // Note that A[0] and A[size-1] won't move
while (i < size) {
cycleBegin = i;
t = A[i];
do {
// Input matrix [r x c]
// Output matrix
// i_new = (i*r)%size
next = (i * r) % size;
char temp = t;
t = A[next];
A[next] = temp;
b |= (1 << i);
i = next;
} while (i != cycleBegin);
// Get Next Move (what about querying random
// location?)
for (i = 1; i < size && ((b & (1 << i)) != 0);
i++)
;
System.out.print("\n");
}
}
static void Fill(char[] buf, int size)
{
// Fill abcd ...
char[] intters
= { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
for (var i = 0; i < size; i++)
buf[i] = intters[i];
// Fill 0123 ...
for (var i = size; i < 2 * size; i++)
buf[i] = (char)(48 + i - size);
}
static void TestCase_01()
{
int r = 2, c = 10;
int size = r * c;
char[] A = new char[size];
Fill(A, c);
Print2DArray(A, r, c);
MatrixTransposeInplaceArrangement(A, r, c);
Print2DArray(A, c, r);
System.out.print("\n");
}
public static void main(String[] args)
{
TestCase_01();
}
}
// This code is contributed by phasing17.
Python3
HASH_SIZE = 128
def Print2DArray(A, nr, nc):
size = nr*nc
for i in range(size):
print(str(A[i]).rjust(4), end="")
def MatrixTransposeInplaceArrangement(A, r, c):
size = r*c - 1
b = 1 # hash to mark moved elements
b |= (1 << size)
i = 1 # Note that A[0] and A[size-1] won't move
while(i < size):
cycleBegin = i
t = A[i]
while True:
# Input matrix [r x c]
# Output matrix [c x r]
# i_new = (i*r)%size
next1 = (i*r) % size
t, A[next1] = A[next1], t
b |= (1 << i)
i = next1
if (i == cycleBegin):
break
# Get next1 Move (what about querying random location?)
i = 1
while (i < size and (b & (1 << i)) != 0):
i += 1
print()
def Fill(buf, size):
# Fill abcd ...
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
for i in range(size):
buf[i] = letters[i]
# Fill 0123 ..
for i in range(size, 2 * size):
buf[i] = str(i - size)
def TestCase_01():
r = 2
c = 10
size = r*c
A = [0] * size
Fill(A, c)
Print2DArray(A, r, c)
MatrixTransposeInplaceArrangement(A, r, c)
Print2DArray(A, c, r)
print()
TestCase_01()
C#
using System;
using System.Collections.Generic;
class GFG {
static int HASH_SIZE = 128;
static void Print2DArray(char[] A, int nr, int nc)
{
int size = nr * nc;
for (int i = 0; i < size; i++)
Console.Write(
Convert.ToString(A[i]).PadLeft(4));
Console.Write("\n");
}
static void MatrixTransposeInplaceArrangement(char[] A,
int r,
int c)
{
int size = r * c - 1;
char t; // holds element to be replaced, eventually
// becomes next element to move
int next; // location of 't' to be moved
int cycleBegin; // holds start of cycle
int i; // iterator
int b = 1; // hash to mark moved elements
b |= (1 << size);
i = 1; // Note that A[0] and A[size-1] won't move
while (i < size) {
cycleBegin = i;
t = A[i];
do {
// Input matrix [r x c]
// Output matrix
// i_new = (i*r)%size
next = (i * r) % size;
char temp = t;
t = A[next];
A[next] = temp;
b |= (1 << i);
i = next;
} while (i != cycleBegin);
// Get Next Move (what about querying random
// location?)
for (i = 1; i < size && ((b & (1 << i)) != 0);
i++)
;
Console.Write("\n");
}
}
static void Fill(char[] buf, int size)
{
// Fill abcd ...
char[] intters
= { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
for (var i = 0; i < size; i++)
buf[i] = intters[i];
// Fill 0123 ...
for (var i = size; i < 2 * size; i++)
buf[i] = Convert.ToChar(48 + i - size);
}
static void TestCase_01()
{
int r = 2, c = 10;
int size = r * c;
char[] A = new char[size];
Fill(A, c);
Print2DArray(A, r, c);
MatrixTransposeInplaceArrangement(A, r, c);
Print2DArray(A, c, r);
Console.Write("\n");
}
public static void Main(string[] args)
{
TestCase_01();
}
}
// This code is contributed by phasing17.
JavaScript
let HASH_SIZE = 128
function Print2DArray(A, nr, nc) {
let size = nr*nc;
for(var i = 0; i < size; i++)
process.stdout.write(String(A[i]).padStart(4))
console.log()
}
function MatrixTransposeInplaceArrangement(A, r, c) {
let size = r*c - 1;
let t; // holds element to be replaced, eventually becomes next element to move
let next; // location of 't' to be moved
let cycleBegin; // holds start of cycle
let i; // iterator
let b = 1; // hash to mark moved elements
b |= (1 << size);
i = 1; // Note that A[0] and A[size-1] won't move
while( i < size ) {
cycleBegin = i;
t =A[i]
do {
// Input matrix [r x c]
// Output matrix [c x r]
// i_new = (i*r)%size
next = (i*r)%size;
let temp = t
t = A[next]
A[next] = temp
b |= (1 << i);
i = next;
} while( i != cycleBegin );
// Get Next Move (what about querying random location?)
for(i = 1; i < size && (b & (1 << i)); i++)
;
console.log()
}
}
function Fill(buf, size) {
// Fill abcd ...
let letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
for(var i = 0; i < size; i++)
buf[i] = letters[i];
// Fill 0123 ...
for(var i = size; i < 2 * size; i++)
buf[i] = String(i - size);
}
function TestCase_01() {
let r = 2, c = 10;
let size = r*c;
let A = new Array(size);
Fill(A, c);
Print2DArray(A, r, c);
MatrixTransposeInplaceArrangement(A, r, c);
Print2DArray(A, c, r)
console.log()
}
TestCase_01();
// This code is contributed by phasing17.
Output a b c d e f g h i j 0 1 2 3 4 5 6 7 8 9
a 0 b 1 c 2 d 3 e 4 f 5 g 6 h 7 i 8 j 9
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Update 09-July-2016: Notes on space complexity and storage order.
After long time, it happened to review this post. Some readers pointed valid questions on how can it be in-place (?) when we are using bitset as marker (hash in code). Apologies for incorrect perception by looking at the article heading or content. While preparing the initial content, I was thinking of naive implementation using auxiliary space of atleast O(MN) needed to transpose rectangular matrix. The program presented above is using constant space as bitset size is fixed at compile time. However, to support arbitrary size of matrices we need bitset size atleast O(MN) size. One can use a HashMap (amortized O(1) complexity) for marking finished locations, yet HashMap's worst case complexity can be O(N) or O(log N) based on implementation. HashMap space cost also increases based on items inserted. Please note that in-place was used w.r.t. matrix space.
Also, it was assumed that the matrix will be stored in row major ordering (contigueous locations in memory). The reader can derive the formulae, if the matrix is represented in column major order by the programming language (e.g. Fortran/Julia).
Thanks to the readers who pointed these two gaps.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The post is incomplete without mentioning two links.
1. Aashish covered good theory behind cycle leader algorithm. See his post on string transformation.
2. As usual, Sambasiva demonstrated his exceptional skills in recursion to the problem. Ensure to understand his solution.
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem