Count inversions of size k in a given array
Last Updated :
02 Jan, 2023
Given an array of n distinct integers a_{1}, a_{2}, ..., a_{n} and an integer k. Find out the number of sub-sequences of a such that a_{i_{1}} > a_{i_{2}} > ... > a_{i_{k}} , and 1 <= i_{1} < i_{2} < ... < i_{k} <= n . In other words output the total number of inversions of length k. Examples:
Input : a[] = {9, 3, 6, 2, 1}, k = 3
Output : 7
The seven inversions are {9, 3, 2}, {9, 3, 1},
{9, 6, 2}, {9, 6, 1}, {9, 2, 1}, {3, 2, 1} and
{6, 2, 1}.
Input : a[] = {5, 6, 4, 9, 2, 7, 1}, k = 4
Output : 2
The two inversions are {5, 4, 2, 1}, {6, 4, 2, 1}.
We have already discussed counting inversion of length three here. This post will generalise the approach using Binary Indexed Tree and Counting inversions using BIT. More on Binary Indexed Trees can be found from the actual paper that Peter M. Fenwick published, here. 1. To begin with, we first convert the given array to a permutation of elements 1, 2, 3, ..., n (Note that this is always possible since the elements are distinct). 2. The approach is to maintain a set of k Fenwick Trees. Let it be denoted by bit[k][n] where bit[l][x] , keeps track of the number of l - length sub-sequences that start with x . 3. We iterate from the end of the converted array to the beginning. For every converted array element x , we update the Fenwick tree set, as: For each 1 <= l <= k , each sub-sequence of length l that start with a number less than x is also a part of sequences of length l+1 . The final result is found by sum of occurrences of (k, n) . The implementation is discussed below:
C++
// C++ program to count inversions of size k using
// Binary Indexed Tree
#include <bits/stdc++.h>
using namespace std;
// It is beneficial to declare the 2D BIT globally
// since passing it into functions will create
// additional overhead
const int K = 51;
const int N = 100005;
int BIT[K][N] = { 0 };
// update function. "t" denotes the t'th Binary
// indexed tree
void updateBIT(int t, int i, int val, int n)
{
// Traversing the t'th BIT
while (i <= n) {
BIT[t][i] = BIT[t][i] + val;
i = i + (i & (-i));
}
}
// function to get the sum.
// "t" denotes the t'th Binary indexed tree
int getSum(int t, int i)
{
int res = 0;
// Traversing the t'th BIT
while (i > 0) {
res = res + BIT[t][i];
i = i - (i & (-i));
}
return res;
}
// Converts an array to an array with values from 1 to n
// and relative order of smaller and greater elements
// remains same. For example, {7, -90, 100, 1} is
// converted to {3, 1, 4, 2 }
void convert(int arr[], int n)
{
// Create a copy of arr[] in temp and sort
// the temp array in increasing order
int temp[n];
for (int i = 0; i < n; i++)
temp[i] = arr[i];
sort(temp, temp + n);
// Traverse all array elements
for (int i = 0; i < n; i++) {
// lower_bound() Returns pointer to the
// first element greater than or equal
// to arr[i]
arr[i] = lower_bound(temp, temp + n,
arr[i]) - temp + 1;
}
}
// Returns count of inversions of size three
int getInvCount(int arr[], int n, int k)
{
// Convert arr[] to an array with values from
// 1 to n and relative order of smaller and
// greater elements remains same. For example,
// {7, -90, 100, 1} is converted to {3, 1, 4, 2 }
convert(arr, n);
// iterating over the converted array in
// reverse order.
for (int i = n - 1; i >= 0; i--) {
int x = arr[i];
// update the BIT for l = 1
updateBIT(1, x, 1, n);
// update BIT for all other BITs
for (int l = 1; l < k; l++) {
updateBIT(l + 1, x, getSum(l, x - 1), n);
}
}
// final result
return getSum(k, n);
}
// Driver program to test above function
int main()
{
int arr[] = { 5, 6, 4, 9, 3, 7, 2, 1 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 4;
cout << "Inversion Count : " << getInvCount(arr, n, k);
return 0;
}
Java
// Java program to count
// inversions of size k using
// Binary Indexed Tree
import java.io.*;
import java.util.Arrays;
import java.util.ArrayList;
import java.lang.*;
import java.util.Collections;
class GFG
{
// It is beneficial to declare
// the 2D BIT globally since
// passing it into functions
// will create additional overhead
static int K = 51;
static int N = 100005;
static int BIT[][] = new int[K][N];
// update function. "t" denotes
// the t'th Binary indexed tree
static void updateBIT(int t, int i,
int val, int n)
{
// Traversing the t'th BIT
while (i <= n)
{
BIT[t][i] = BIT[t][i] + val;
i = i + (i & (-i));
}
}
// function to get the sum.
// "t" denotes the t'th
// Binary indexed tree
static int getSum(int t, int i)
{
int res = 0;
// Traversing the t'th BIT
while (i > 0)
{
res = res + BIT[t][i];
i = i - (i & (-i));
}
return res;
}
// Converts an array to an
// array with values from
// 1 to n and relative order
// of smaller and greater
// elements remains same.
// For example, {7, -90, 100, 1}
// is converted to {3, 1, 4, 2 }
static void convert(int arr[], int n)
{
// Create a copy of arr[] in
// temp and sort the temp
// array in increasing order
int temp[] = new int[n];
for (int i = 0; i < n; i++)
temp[i] = arr[i];
Arrays.sort(temp);
// Traverse all array elements
for (int i = 0; i < n; i++)
{
// lower_bound() Returns
// pointer to the first
// element greater than
// or equal to arr[i]
arr[i] = Arrays.binarySearch(temp,
arr[i]) + 1;
}
}
// Returns count of inversions
// of size three
static int getInvCount(int arr[],
int n, int k)
{
// Convert arr[] to an array
// with values from 1 to n and
// relative order of smaller
// and greater elements remains
// same. For example, {7, -90, 100, 1}
// is converted to {3, 1, 4, 2 }
convert(arr, n);
// iterating over the converted
// array in reverse order.
for (int i = n - 1; i >= 0; i--)
{
int x = arr[i];
// update the BIT for l = 1
updateBIT(1, x, 1, n);
// update BIT for all other BITs
for (int l = 1; l < k; l++)
{
updateBIT(l + 1, x,
getSum(l, x - 1), n);
}
}
// final result
return getSum(k, n);
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 5, 6, 4, 9,
3, 7, 2, 1 };
int n = arr.length;
int k = 4;
System.out.println("Inversion Count : " +
getInvCount(arr, n, k));
}
}
Python3
# Python3 program to count inversions
# of size k using Binary Indexed Tree
# It is beneficial to declare the 2D BIT
# globally since passing it o functions
# will create additional overhead
K = 51
N = 100005
BIT = [[0 for x in range(N)]
for y in range(K)]
# update function. "t" denotes
# the t'th Binary indexed tree
def updateBIT(t, i, val, n):
# Traversing the t'th BIT
while (i <= n):
BIT[t][i] = BIT[t][i] + val
i = i + (i & (-i))
# function to get the sum. "t" denotes
# the t'th Binary indexed tree
def getSum(t, i):
res = 0
# Traversing the t'th BIT
while (i > 0):
res = res + BIT[t][i]
i = i - (i & (-i))
return res
# Converts an array to an array with
# values from 1 to n and relative order
# of smaller and greater elements remains
# same. For example, 7, -90, 100, 1 is
# converted to 3, 1, 4, 2
def convert( arr, n):
# Create a copy of arr[] in temp and sort
# the temp array in increasing order
temp = [0] * n
for i in range(n):
temp[i] = arr[i]
temp = sorted(temp)
j = 1
for i in temp:
arr[arr.index(i)] = j
j += 1
# Returns count of inversions
# of size three
def getInvCount(arr, n, k) :
# Convert arr[] to an array with
# values from 1 to n and relative
# order of smaller and greater elements
# remains same. For example, 7, -90, 100, 1
# is converted to 3, 1, 4, 2
convert(arr, n)
# iterating over the converted array
# in reverse order.
for i in range(n - 1, -1, -1):
x = arr[i]
# update the BIT for l = 1
updateBIT(1, x, 1, n)
# update BIT for all other BITs
for l in range(1, k):
updateBIT(l + 1, x, getSum(l, x - 1), n)
# final result
return getSum(k, n)
# Driver code
if __name__ =="__main__":
arr = [5, 6, 4, 9, 3, 7, 2, 1]
n = 8
k = 4
print("Inversion Count :",
getInvCount(arr, n, k))
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)
C#
// C# program to count
// inversions of size k using
// Binary Indexed Tree
using System;
using System.Linq;
class GFG
{
// It is beneficial to declare
// the 2D BIT globally since
// passing it into functions
// will create additional overhead
static int K = 51;
static int N = 100005;
static int [,]BIT = new int[K, N];
// update function. "t" denotes
// the t'th Binary indexed tree
static void updateBIT(int t, int i,
int val, int n)
{
// Traversing the t'th BIT
while (i <= n)
{
BIT[t, i] = BIT[t, i] + val;
i = i + (i & (-i));
}
}
// function to get the sum.
// "t" denotes the t'th
// Binary indexed tree
static int getSum(int t, int i)
{
int res = 0;
// Traversing the t'th BIT
while (i > 0)
{
res = res + BIT[t, i];
i = i - (i & (-i));
}
return res;
}
// Converts an array to an
// array with values from
// 1 to n and relative order
// of smaller and greater
// elements remains same.
// For example, {7, -90, 100, 1}
// is converted to {3, 1, 4, 2 }
static void convert(int []arr, int n)
{
// Create a copy of arr[] in
// temp and sort the temp
// array in increasing order
int []temp = new int[n];
for (int i = 0; i < n; i++)
temp[i] = arr[i];
Array.Sort(temp);
// Traverse all array elements
for (int i = 0; i < n; i++)
{
// lower_bound() Returns
// pointer to the first
// element greater than
// or equal to arr[i]
arr[i] = Array.BinarySearch(temp,
arr[i]) + 1;
}
}
// Returns count of inversions
// of size three
static int getInvCount(int []arr,
int n, int k)
{
// Convert arr[] to an array
// with values from 1 to n and
// relative order of smaller
// and greater elements remains
// same. For example, {7, -90, 100, 1}
// is converted to {3, 1, 4, 2 }
convert(arr, n);
// iterating over the converted
// array in reverse order.
for (int i = n - 1; i >= 0; i--)
{
int x = arr[i];
// update the BIT for l = 1
updateBIT(1, x, 1, n);
// update BIT for all other BITs
for (int l = 1; l < k; l++)
{
updateBIT(l + 1, x,
getSum(l, x - 1), n);
}
}
// final result
return getSum(k, n);
}
// Driver Code
public static void Main(String[] args)
{
int []arr = { 5, 6, 4, 9,
3, 7, 2, 1 };
int n = arr.Length;
int k = 4;
Console.WriteLine("Inversion Count : " +
getInvCount(arr, n, k));
}
}
// This code is contributed by PrinciRaj1992
JavaScript
// Javascript program to count inversions of size k using
// Binary Indexed Tree
// It is beneficial to declare the 2D BIT globally
// since passing it into functions will create
// additional overhead
let K = 51;
let N = 100005;
let BIT = new Array(K).fill(0).map(() => new Array(N).fill(0));
// update function. "t" denotes the t'th Binary
// indexed tree
function updateBIT(t, i, val, n)
{
// Traversing the t'th BIT
while (i <= n) {
BIT[t][i] = BIT[t][i] + val;
i = i + (i & (-i));
}
}
// function to get the sum.
// "t" denotes the t'th Binary indexed tree
function getSum(t, i)
{
let res = 0;
// Traversing the t'th BIT
while (i > 0) {
res = res + BIT[t][i];
i = i - (i & (-i));
}
return res;
}
// Converts an array to an array with values from 1 to n
// and relative order of smaller and greater elements
// remains same. For example, {7, -90, 100, 1} is
// converted to {3, 1, 4, 2 }
function convert(arr, n)
{
// Create a copy of arr[] in temp and sort
// the temp array in increasing order
let temp=new Array(n);
for (let i = 0; i < n; i++)
temp[i] = arr[i];
temp.sort();
// Traverse all array elements
for (let i = 0; i < n; i++) {
// lower_bound() Returns pointer to the
// first element greater than or equal
// to arr[i]
arr[i] = lower_bound(temp, 0, n, arr[i])+1;
}
}
function lower_bound(a, low, high, element)
{
while(low < high)
{
let middle = low + parseInt((high - low) / 2, 10);
if(element > a[middle])
low = middle + 1;
else
high = middle;
}
return low;
}
// Returns count of inversions of size three
function getInvCount(arr, n, k)
{
// Convert arr[] to an array with values from
// 1 to n and relative order of smaller and
// greater elements remains same. For example,
// {7, -90, 100, 1} is converted to {3, 1, 4, 2 }
convert(arr, n);
// iterating over the converted array in
// reverse order.
for (let i = n - 1; i >= 0; i--) {
let x = arr[i];
// update the BIT for l = 1
updateBIT(1, x, 1, n);
// update BIT for all other BITs
for (let l = 1; l < k; l++) {
updateBIT(l + 1, x, getSum(l, x - 1), n);
}
}
// final result
return getSum(k, n);
}
// Driver program to test above function
let arr = [ 5, 6, 4, 9, 3, 7, 2, 1 ];
let n = arr.length;
let k = 4;
console.log("Inversion Count : " + getInvCount(arr, n, k));
// This code is contributed by Pushpesh Raj.
Output:
Inversion Count : 11
Time Complexity \mathcal{O}(nklog(n)) Auxiliary Space \mathcal{O}(nk) It should be noted that this is not the only approach to solve the problem of finding k-inversions. Obviously, any problem solvable by BIT is also solvable by Segment Tree. Besides, we can use Merge-Sort based algorithm, and C++ policy based data structure too. Also, at the expense of higher time complexity, Dynamic Programming approach can also be used.
Similar Reads
Count Inversions of size three in a given array
Given an array arr[] of size n. Three elements arr[i], arr[j] and arr[k] form an inversion of size 3 if a[i] > a[j] >a[k] and i < j < k. Find total number of inversions of size 3. Example : Input: {8, 4, 2, 1} Output: 4 The four inversions are (8,4,2), (8,4,1), (4,2,1) and (8,2,1). Input
15+ min read
Count inversions in a sequence generated by appending given array K times
Given an array arr[], the task is to append the given array exactly K - 1 times to its end and print the total number of inversions in the resulting array. Examples: Input: arr[]= {2, 1, 3}, K = 3Output: 12Explanation:Appending 2 copies of array arr[] modifies arr[] to {2, 1, 3, 2, 1, 3, 2, 1, 3}The
7 min read
Count all possible pairs in given Array with product K
Given an integer array arr[] of size N and a positive integer K, the task is to count all the pairs in the array with a product equal to K. Examples: Input: arr[] = {1, 2, 16, 4, 4, 4, 8 }, K=16Output: 5Explanation: Possible pairs are (1, 16), (2, 8), (4, 4), (4, 4), (4, 4) Input: arr[] = {1, 10, 20
11 min read
Count frequency of digit K in given Array
Given an array arr[] of integers of size N and a single digit integer K. The task is to find the total count of occurrences of the digit K in the array Examples: Input: arr[] = {15, 66, 26, 91}, K = 6Output: 3Explanation: Occurrences of 6 in each array elements are: 0, 2, 1, 0 respectively.Therefore
5 min read
Count subsets in an array having product K
Given an array arr[] of size N, the task is to find the count of all subsets from the given array whose product of is equal to K. Examples: Input: arr[] = { 1, 1, 2, 2, 3 }, K = 4 Output: 4 Explanation: Subsets with product equal to K(= 4) are: { { arr[0], arr[1], arr[2], arr[3] }, { arr[0], arr[2],
12 min read
Count of K-countdowns in an Array
Given an array arr[] of length N and a number K, the task is to count the number of K-countdowns in the array. A contiguous subarray is said to be a K-countdown if it is of length K and contains the integers K, K-1, K-2, ..., 2, 1 in that order. For example, [4, 3, 2, 1] is 4-countdown and [6, 5, 4,
7 min read
Queries for counts of multiples in an array
Given an array of positive integers and many queries for divisibility. In every query, we are given an integer k ( > 0), we need to count all elements in the array which are perfectly divisible by 'k'. Example: Input:2 4 9 15 21 20k = 2k = 3k = 5Output:332Explanation:Multiples of '2' in array are
9 min read
Count of integers in an Array whose length is a multiple of K
Given an array arr of N elements and an integer K, the task is to count all the elements whose length is a multiple of K.Examples: Input: arr[]={1, 12, 3444, 544, 9}, K = 2 Output: 2 Explanation: There are 2 numbers whose digit count is multiple of 2 {12, 3444}. Input: arr[]={12, 345, 2, 68, 7896},
5 min read
Count pairs in array whose sum is divisible by K
Given an array A[] and positive integer K, the task is to count the total number of pairs in the array whose sum is divisible by K. Note: This question is a generalized version of this Examples: Input : A[] = {2, 2, 1, 7, 5, 3}, K = 4 Output : 5 Explanation : There are five pairs possible whose sum
10 min read
Count ways to select K array elements lying in a given range
Given three positive integers, L, R, K and an array arr[] consisting of N positive integers, the task is to count the number of ways to select at least K array elements from the given array having values in the range [L, R]. Examples: Input: arr[] = {12, 4, 6, 13, 5, 10}, K = 3, L = 4, R = 10 Output
9 min read