Count inversion pairs in a matrix
Last Updated :
24 Feb, 2023
Given a matrix A of size NxN, we need to find the number of inversion pairs in it. Inversion count in a matrix is defined as the number of pairs satisfying the following conditions :
- x1 ? x2
- y1 ? y2
- A[x2][y2] < A[x1][y1]
Constraints :
- 1 ? Ai,j ? 109
- 1 ? N ? 103
Examples:
For simplicity, let's take a 2x2 matrix :
A = {{7, 5},
{3, 1}};
The inversion pairs are : (7, 5), (3, 1), (7, 3), (5, 1) and (7, 1)
Output : 5
To solve this problem, we need to know the following things :
- Finding number of inversion pairs in a 1D array using Binary Indexed Tree (BIT) https://www.geeksforgeeks.org/count-inversions-array-set-3-using-bit
- 2D BIT https://www.geeksforgeeks.org/two-dimensional-binary-indexed-tree-or-fenwick-tree
Since, we need to find number of inversion pairs in a matrix, first thing we need to do is to store the elements of the matrix in another array, say v and sort the array v so that we can compare the elements of the unsorted matrix with v and find the number of inversion pairs using BIT. But it is given that the values of the elements are very large (109), so we cannot use the values of the elements in the matrix as indices in the BIT. Thus, we need to use the position of the elements as indexes in the 2D BIT.
We are going to use the tuple (-A[i][j], i, j) for each element of the matrix and store it in an array, say 'v'. Then we need to sort v according to the value of -A[i][j] in ascending order, so that the largest element of the matrix will be stored at index 0 and the smallest one at the last index of v. Now, the problem is reduced to finding inversion pairs in a 1D array, the only exception is that we are going to use a 2D BIT.
Note that here we are using negative values of A[i][j], simply because we are going to traverse v from left to right, i.e., from the largest number in the matrix to the smallest one(because that's what we do when finding inversion pairs in a 1D array using BIT). One can also use positive values and traverse v from right to left fashion, final result will remain same.
Algorithm :
1. Initialize inv_pair_cnt = 0, which will store the number of inversion pairs.
2. Store the tuple (-A[i][j], i, j) in an array, say v, where A[i][j] is the
element of the matrix A at position (i, j).
3. Sort the array v according to the first element of the tuple, i.e.,
according to the value of -A[i][j].
4. Traverse the array v and do the following :
- Initialize an array, say 'pairs' to store the position (i, j)
of the tuples of v.
- while the current tuple of v and all its adjacent tuples whose
first value, i.e., -A[i][j] is same, do
- Push the current tuple's position pair (i, j) into 'pairs'.
- Add to inv_pair_cnt, the number of elements which are less than
the current element(i.e., A[i][j]) and lie on the right side
in the sorted array v, by calling the query operation of BIT and
passing i and j as arguments.
- For each position pair (i, j) stored in the array 'pairs',
update the position (i, j) in the 2D BIT by 1.
5. Finally, inv_pair_cnt will contain the number of inversion pairs.
Implementation:
C++
// C++ program to count the number of inversion
// pairs in a 2D matrix
#include <bits/stdc++.h>
using namespace std;
// for simplicity, we are taking N as 4
#define N 4
void update(int l, int r, int val, int bit[][N + 1])
{
for (int i = l; i <= N; i += i & -i)
for (int j = r; j <= N; j += j & -j)
bit[i][j] += val;
}
// function to find cumulative sum upto
// index (l, r) in the 2D BIT
long long query(int l, int r, int bit[][N + 1])
{
long long ret = 0;
for (int i = l; i > 0; i -= i & -i)
for (int j = r; j > 0; j -= j & -j)
ret += bit[i][j];
return ret;
}
// function to count and return the number
// of inversion pairs in the matrix
long long countInversionPairs(int mat[][N])
{
// the 2D bit array and initialize it with 0.
int bit[N+1][N+1] = {0};
// v will store the tuple (-mat[i][j], i, j)
vector<pair<int, pair<int, int> > > v;
// store the tuples in the vector v
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
v.push_back(make_pair(-mat[i][j],
make_pair(i+1, j+1)));
sort(v.begin(), v.end());
// inv_pair_cnt will store the number of
// inversion pairs
long long inv_pair_cnt = 0;
// traverse all the tuples of vector v
int i = 0;
while (i < v.size())
{
int curr = i;
vector<pair<int, int> > pairs;
while (curr < v.size() &&
(v[curr].first == v[i].first))
{
// push the position of the current element in 'pairs'
pairs.push_back(make_pair(v[curr].second.first,
v[curr].second.second));
inv_pair_cnt += query(v[curr].second.first,
v[curr].second.second, bit);
curr++;
}
vector<pair<int, int> >::iterator it;
// traverse the 'pairs' vector
for (it = pairs.begin(); it != pairs.end(); ++it)
{
int x = it->first;
int y = it->second;
// update the position (x, y) by 1
update(x, y, 1, bit);
}
i = curr;
}
return inv_pair_cnt;
}
// Driver program
int main()
{
int mat[N][N] = { { 4, 7, 2, 9 },
{ 6, 4, 1, 7 },
{ 5, 3, 8, 1 },
{ 3, 2, 5, 6 } };
long long inv_pair_cnt = countInversionPairs(mat);
cout << "The number of inversion pairs are : "
<< inv_pair_cnt << endl;
return 0;
}
Python3
# Python3 program to count the number of inversion
# pairs in a 2D matrix
# for simplicity, we are taking N as 4
N = 4
# Function to update a 2D BIT. It updates the
# value of bit[l][r] by adding val to bit[l][r]
def update(l, r, val, bit):
i = l
while(i <= N):
j = r
while(j <= N):
bit[i][j] += val
j += j & -j
i += i & -i
# function to find cumulative sum upto
# index (l, r) in the 2D BIT
def query(l, r, bit):
ret = 0
i = l
while(i > 0):
j = r
while(j > 0):
ret += bit[i][j]
j -= j & -j
i -= i & -i
return ret
# function to count and return the number
# of inversion pairs in the matrix
def countInversionPairs(mat):
# the 2D bit array and initialize it with 0.
bit = [[0 for i in range(N + 1)] for j in range(N + 1)]
# v will store the tuple (-mat[i][j], i, j)
v = []
# store the tuples in the vector v
for i in range(N):
for j in range(N):
# Note that we are not using the pair
# (0, 0) because BIT update and query
# operations are not done on index 0
v.append([-mat[i][j], [i + 1, j + 1]])
# sort the vector v according to the
# first element of the tuple, i.e., -mat[i][j]
v.sort()
# inv_pair_cnt will store the number of
# inversion pairs
inv_pair_cnt = 0
# traverse all the tuples of vector v
i = 0
while (i < len(v)):
curr = i
# 'pairs' will store the position of each element,
# i.e., the pair (i, j) of each tuple of the vector v
pairs = []
# consider the current tuple in v and all its
# adjacent tuples whose first value, i.e., the
# value of –mat[i][j] is same
while (curr < len(v) and (v[curr][0] == v[i][0])):
# push the position of the current element in 'pairs'
pairs.append([v[curr][1][0], v[curr][1][1]])
# add the number of elements which are
# less than the current element and lie on the right
# side in the vector v
inv_pair_cnt += query(v[curr][1][0], v[curr][1][1], bit)
curr += 1
# traverse the 'pairs' vector
for it in pairs:
x = it[0]
y = it[1]
# update the position (x, y) by 1
update(x, y, 1, bit)
i = curr
return inv_pair_cnt
# Driver code
mat = [[4, 7, 2, 9 ],[ 6, 4, 1, 7 ],
[ 5, 3, 8, 1 ],[3, 2, 5, 6]]
inv_pair_cnt = countInversionPairs(mat)
print("The number of inversion pairs are :", inv_pair_cnt)
# This code is contributed by shubhamsingh10
C#
// C# program to count the number of inversion
// Tuples in a 2D matrix
using System;
using System.Collections.Generic;
class GFG
{
// for simplicity, we are taking N as 4
static int N = 4;
// Function to update a 2D BIT. It updates the
// value of bit[l, r] by adding val to bit[l, r]
static void update(int l, int r, int val, int[,] bit)
{
for (int x = l; x <= N; x += (x & -x))
for (int j = r; j <= N; j += j & -j)
bit[x, j] += val;
}
// function to find cumulative sum upto
// index (l, r) in the 2D BIT
static int query(int l, int r, int[,] bit)
{
int ret = 0;
for (int x = l; x > 0; x -= (x & -x))
for (int j = r; j > 0; j -= (j & -j))
ret += bit[x, j];
return ret;
}
// function to count and return the number
// of inversion Tuples in the matrix
static int countInversionTuples(int[,] mat)
{
// the 2D bit array and initialize it with 0.
int[, ] bit = new int[N + 1, N +1];
for (int x = 0; x <= N; x++)
for (int y = 0; y <= N; y++)
bit[x, y] = 0;
// v will store the tuple (-mat[i, j], i, j)
List<Tuple<int, Tuple<int, int> > > v = new List<Tuple<int, Tuple<int, int> > >();
// store the tuples in the vector v
for (int x = 0; x < N; ++x)
for (int j = 0; j < N; ++j)
// Note that we are not using the Tuple
// (0, 0) because BIT update and query
// operations are not done on index 0
v.Add(Tuple.Create(-mat[x, j],
Tuple.Create(x+1, j+1)));
// sort the vector v according to the
// first element of the tuple, i.e., -mat[i, j]
v.Sort();
// inv_Tuple_cnt will store the number of
// inversion Tuples
int inv_Tuple_cnt = 0;
// traverse all the tuples of vector v
int i = 0;
while (i < v.Count)
{
int curr = i;
// 'Tuples' will store the position of each element,
// i.e., the Tuple (i, j) of each tuple of the vector v
List<Tuple<int, int>> Tuples = new List<Tuple<int, int>>();
// consider the current tuple in v and all its
// adjacent tuples whose first value, i.e., the
// value of –mat[i, j] is same
while (curr < v.Count &&
(v[curr].Item1 == v[i].Item1))
{
// push the position of the current element in 'Tuples'
Tuples.Add(Tuple.Create(v[curr].Item2.Item1,
v[curr].Item2.Item2));
// add the number of elements which are
// less than the current element and lie on the right
// side in the vector v
inv_Tuple_cnt += query(v[curr].Item2.Item1,
v[curr].Item2.Item2, bit);
curr++;
}
// traverse the 'Tuples' vector
foreach (var it in Tuples)
{
int x = it.Item1;
int y = it.Item2;
// update the position (x, y) by 1
update(x, y, 1, bit);
}
i = curr;
}
return inv_Tuple_cnt;
}
// Driver program
public static void Main(string[] args)
{
int[, ] mat = { { 4, 7, 2, 9 },
{ 6, 4, 1, 7 },
{ 5, 3, 8, 1 },
{ 3, 2, 5, 6 } };
int inv_Tuple_cnt = countInversionTuples(mat);
Console.WriteLine( "The number of inversion Tuples are : " + inv_Tuple_cnt);
}
}
// This code is contributed by phasing17.
JavaScript
// JavaScript program to count the number of inversion
// pairs in a 2D matrix
// for simplicity, we are taking N as 4
let N = 4
// Function to update a 2D BIT. It updates the
// value of bit[l][r] by adding val to bit[l][r]
function update(l, r, val, bit)
{
let i = l
while(i <= N)
{
let j = r
while(j <= N)
{
bit[i][j] += val
j += (j & -j)
}
i += (i & -i)
}
return bit
}
// function to find cumulative sum upto
// index (l, r) in the 2D BIT
function query(l, r, bit)
{
let ret = 0
let i = l
while(i > 0)
{
let j = r
while(j > 0)
{
ret += bit[i][j]
j -= (j & -j)
}
i -= (i & -i)
}
return ret
}
// function to count and return the number
// of inversion pairs in the matrix
function countInversionPairs(mat)
{
// the 2D bit array and initialize it with 0.
let bit = new Array(N + 1)
for (let i = 0; i <= N; i++)
bit[i] = new Array(N + 1).fill(0)
// v will store the tuple (-mat[i][j], i, j)
let v = []
// store the tuples in the vector v
for (let i = 0; i < N; i++)
for (var j = 0; j < N; j++)
// Note that we are not using the pair
// (0, 0) because BIT update and query
// operations are not done on index 0
v.push([-mat[i][j], [i + 1, j + 1]])
// sort the vector v according to the
// first element of the tuple, i.e., -mat[i][j]
v.sort(function(a, b) { return a[0] - b[0]})
// inv_pair_cnt will store the number of
// inversion pairs
let inv_pair_cnt = 0
// traverse all the tuples of vector v
let i = 0
while (i < v.length)
{
let curr = i
// 'pairs' will store the position of each element,
// i.e., the pair (i, j) of each tuple of the vector v
let pairs = []
// consider the current tuple in v and all its
// adjacent tuples whose first value, i.e., the
// value of –mat[i][j] is same
while (curr < v.length && (v[curr][0] == v[i][0]))
{
// push the position of the current element in 'pairs'
pairs.push([v[curr][1][0], v[curr][1][1]])
// add the number of elements which are
// less than the current element and lie on the right
// side in the vector v
inv_pair_cnt += query(v[curr][1][0], v[curr][1][1], bit)
curr += 1
}
// traverse the 'pairs' vector
for (let it of pairs)
{
let x = it[0]
let y = it[1]
// update the position (x, y) by 1
bit = update(x, y, 1, bit)
}
i = curr
}
return inv_pair_cnt
}
// Driver code
let mat = [[4, 7, 2, 9 ],[ 6, 4, 1, 7 ],
[ 5, 3, 8, 1 ],[3, 2, 5, 6]]
let inv_pair_cnt = countInversionPairs(mat)
console.log("The number of inversion pairs are ", inv_pair_cnt)
// This code is contributed by phasing17
Java
import java.util.*;
class Main {
static final int N = 4;
static void update(int l, int r, int val, int[][] bit) {
for (int i = l; i <= N; i += i & -i)
for (int j = r; j <= N; j += j & -j)
bit[i][j] += val;
}
static long query(int l, int r, int[][] bit) {
long ret = 0;
for (int i = l; i > 0; i -= i & -i)
for (int j = r; j > 0; j -= j & -j)
ret += bit[i][j];
return ret;
}
static long countInversionPairs(int[][] mat) {
int[][] bit = new int[N + 1][N + 1];
List<AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Integer, Integer>>> v = new ArrayList<>();
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
v.add(new AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Integer, Integer>>(-mat[i][j], new AbstractMap.SimpleEntry<Integer, Integer>(i + 1, j + 1)));
Collections.sort(v, new Comparator<AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Integer, Integer>>>() {
@Override
public int compare(AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Integer, Integer>> a, AbstractMap.SimpleEntry<Integer, AbstractMap.SimpleEntry<Integer, Integer>> b) {
return a.getKey().compareTo(b.getKey());
}
});
long invPairCnt = 0;
int i = 0;
while (i < v.size()) {
int curr = i;
List<AbstractMap.SimpleEntry<Integer, Integer>> pairs = new ArrayList<>();
while (curr < v.size() && (v.get(curr).getKey().equals(v.get(i).getKey()))) {
pairs.add(v.get(curr).getValue());
invPairCnt += query(v.get(curr).getValue().getKey(), v.get(curr).getValue().getValue(), bit);
curr++;
}
for (AbstractMap.SimpleEntry<Integer, Integer> p : pairs) {
int x = p.getKey();
int y = p.getValue();
update(x, y, 1, bit);
}
i = curr;
}
return invPairCnt;
}
public static void main(String[] args) {
int[][] mat = {{4, 7, 2, 9}, {6, 4, 1, 7}, {5, 3, 8, 1}, {3, 2, 5, 6}};
long invPairCnt = countInversionPairs(mat);
System.out.println("The number of inversion pairs are: " + invPairCnt);
}
}
// This code is contributed by Prince Kumar
OutputThe number of inversion pairs are : 43
Time Complexity : O(log(NxN)), where N is the size of the matrix
Space Complexity : O(NxN)
Similar Reads
Count of unique rows in a given Matrix
Given a 2D matrix arr of size N*M containing lowercase English letters, the task is to find the number of unique rows in the given matrix. Examples: Input: arr[][]= { {'a', 'b', 'c', 'd'}, {'a', 'e', 'f', 'r'}, {'a', 'b', 'c', 'd'}, {'z', 'c', 'e', 'f'} }Output: 2Explanation: The 2nd and the 4th row
10 min read
Count of palindromic rows in given Matrix
Given a matrix arr[][] of size N * N, the task is to find the number of palindromic rows. Examples: Input: arr[][] = {{1, 3, 1}, {2, 2, 3}, {2, 1, 2}} Output: 2Explanation: First and third row forms a palindrome i.e 1 3 1 and 2 1 2. Therefore, count of palindromic rows is 2. Input: arr[][] = {{2, 2,
4 min read
Count majority element in a matrix
Given a NxM matrix of integers containing duplicate elements. The task is to find the count of all majority occurring elements in the given matrix, where majority element are those whose frequency is greater than or equal to (N*M)/2. Examples: Input : mat[] = {{1, 1, 2}, {2, 3, 3}, {4, 3, 3}} Output
6 min read
Count of palindromic plus paths in a given Matrix
Given an N x M matrix of integers, the task is to count the number of palindromic pluses in the array. Palindromic plus is formed when a palindromic sub-row and palindromic sub-column cross each other at the middle element. Examples: Input: matrix = [[1, 2, 1], [2, 3, 2], [3, 2, 1]] Output: 1 Explan
6 min read
Count entries equal to x in a special matrix
You are given a square matrix (matrix[][]) of order n, where matrix[i][j] = i*j. Find the number of cells which have entry equal to a given number x. NOte : Indexing of matrix starts from 1, i.e. 1<= i,j <= n. Examples : Input : matrix[][] = {1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16}
6 min read
Count of submatrix with sum X in a given Matrix
Given a matrix of size N x M and an integer X, the task is to find the number of sub-squares in the matrix with sum of elements equal to X.Examples: Input: N = 4, M = 5, X = 10, arr[][]={{2, 4, 3, 2, 10}, {3, 1, 1, 1, 5}, {1, 1, 2, 1, 4}, {2, 1, 1, 1, 3}} Output: 3 Explanation: {10}, {{2, 4}, {3, 1}
15+ min read
Count digits present in each element of a given Matrix
Given a matrix arr[][] of dimensions M * N, the task is to count the number of digits of every element present in the given matrix. Examples: Input: arr[][] = { { 27, 173, 5 }, { 21, 6, 624 }, { 5, 321, 49 } }Output: 2 3 12 1 31 3 2 Input: arr[][] = { {11, 12, 33 }, { 64, 57, 61 }, { 74, 88, 39 } }O
5 min read
Count all sorted rows in a matrix
Given a matrix of m*n size, the task is to count all the rows in a matrix that are sorted either in strictly increasing order or in strictly decreasing order?Examples : Input : m = 4, n = 5 mat[m][n] = 1 2 3 4 5 4 3 1 2 6 8 7 6 5 4 5 7 8 9 10Output: 3The idea is simple and involves two traversals of
10 min read
Count divisible pairs in an array
Given an array, count pairs in the array such that one element of the pair divides the other. Examples: Input : arr[] = {1, 2, 3} Output : 2 The two pairs are (1, 2) and (1, 3) Input : arr[] = {2, 3, 5, 7} Output: 0 Naive Approach: The brute force approach can be implemented by iterating through eve
10 min read
Count submatrices having only 'X' in given Matrix
Given a character matrix consisting of O's and X's, find the number of submatrices containing only 'X' and surrounded by 'O' from all sides. Examples: Input:  grid[][] = {{X, O, X}, {O, X, O}, {X, X, X}}Output: 3 Input: grid[][] = { { 'X', 'O', 'X', 'X' }, { 'O', 'O', 'X', 'X' }, { 'X', 'X', 'O', '
13 min read