Open In App

Count-based Absolute difference for Array element

Last Updated : 15 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of integers, A[] of size N. For each ith element in the array, calculate the absolute difference between the count of numbers that are to the left of i and are strictly greater than the ith element, and the count of numbers that are to the right of i and are strictly lesser than the ith element.

Examples:

Input: N = 5, A[] = {5, 4, 3, 2, 1}
Output: 4 2 0 2 4 
Explanation: We can see that the required number for the 1st element is |0-4| = 4

Input: N = 5, A[] = {1, 2, 3, 4, 5}
Output: 0 0 0 0 0
Explanation: There is no greater element on the left for any element and no lesser element on the right.

Approach: To solve the problem follow the below idea:

The solution to finding the absolute difference between the number of elements greater than and lesser than each element in a given array, involves using a Binary Index Tree. The approach involves sorting the array and mapping each element to its corresponding index in the sorted array, constructing two Binary Index Trees for counting the number of elements less than each element from the right side and greater than each element from the left side, respectively, and computing the absolute difference between the counts for each element.

Steps that were to follow the above approach:

  • Create a Binary Index Tree object with an array of size n+1 initialized with 0.
  • Sort the given input array and create a map of the sorted array elements with their corresponding indices.
  • Create an array of indices of the input array elements using the map created in the previous step.
  • Create another Binary Index Tree object with an array of size n+1 initialized with 0.
  • Traverse the array of indices from right to left and for each index,  
    • find the number of elements smaller than the current element to its right using the Binary Index Tree created in the previous step, update the Binary Index Tree with the current index, and store the result in a separate array.
  • Reverse the array of indices and repeat the traversal, but this time find the number of elements greater than the current element to its left.
  • For each element in the two arrays created in the two traversals, calculate their absolute difference and store the result in a third array.
  • Return the third array as the final result.

Below is the code to implement the above steps:

C++




#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
 
using namespace std;
 
// Binary Indexed Tree class.
class BinaryIndexTree {
private:
    vector<int> arr;
 
public:
    BinaryIndexTree(int size) {
        arr.resize(size + 1, 0);
    }
 
    void update(int x, int val) {
        if (x == 0)
            return;
        for (; x < arr.size(); x += x & -x)
            arr[x] += val;
    }
 
    int query(int index) {
        if (index == 0)
            return 0;
        int sum = 0;
        for (; index > 0; index -= index & -index)
            sum += arr[index];
        return sum;
    }
};
 
// Function to return the resultant array.
vector<int> retResult(vector<int>& arr, int n) {
    vector<int> arrSorted = arr;
    sort(arrSorted.begin(), arrSorted.end());
 
    unordered_map<int, int> map;
    for (int i = 0; i < arrSorted.size(); i++) {
        map[arrSorted[i]] = i + 1;
    }
 
    vector<int> arrIndexes(arr.size());
    int idx = 0;
    for (int key : arr) {
        arrIndexes[idx++] = map[key];
    }
 
    BinaryIndexTree bitRightLesser(arr.size() + 1);
    vector<int> right(n);
    for (int i = n - 1; i >= 0; i--) {
        right[i] = bitRightLesser.query(arrIndexes[i] - 1);
        bitRightLesser.update(arrIndexes[i], 1);
    }
 
    for (int i = 0; i < n; i++) {
        arrIndexes[i] = n + 1 - arrIndexes[i];
    }
 
    BinaryIndexTree bitLeftGreater(arr.size() + 1);
    vector<int> left(n);
    for (int i = 0; i < n; i++) {
        left[i] = bitLeftGreater.query(arrIndexes[i] - 1);
        bitLeftGreater.update(arrIndexes[i], 1);
    }
 
    vector<int> ret(n);
    for (int i = 0; i < n; i++) {
        ret[i] = abs(right[i] - left[i]);
    }
 
    return ret;
}
 
// Driver's code
int main() {
    vector<int> arr = { 5, 4, 3, 2, 1 };
    int n = arr.size();
 
    // Function call
    vector<int> ret = retResult(arr, n);
 
    cout << "[";
    for (int i = 0; i < ret.size(); i++) {
        cout << ret[i];
        if (i != ret.size() - 1)
            cout << ", ";
    }
    cout << "]" << endl;
 
    return 0;
}
 
// This code is contributed by Prajwal Kandekar


Java




// Java code for the above approach.
import java.util.*;
 
public class Main {
    // Binary Indexed Tree class.
    static class BinaryIndexTree {
        private int[] arr;
 
        public BinaryIndexTree(int size)
        {
            arr = new int[size + 1];
            Arrays.fill(arr, 0);
        }
 
        public void update(int x, int val)
        {
            if (x == 0)
                return;
            for (; x < arr.length; x += x & -x)
                arr[x] += val;
        }
 
        public int query(int index)
        {
            if (index == 0)
                return 0;
            int sum = 0;
            for (; index > 0; index -= index & -index)
                sum += arr[index];
            return sum;
        }
    }
 
    // Function to return the
    // resultant array.
    static int[] retResult(int[] arr, int n)
    {
        int[] arrSorted = Arrays.copyOf(arr, arr.length);
        Arrays.sort(arrSorted);
 
        Map<Integer, Integer> map
            = new HashMap<Integer, Integer>();
        for (int i = 0; i < arrSorted.length; i++) {
            map.put(arrSorted[i], i + 1);
        }
 
        int[] arrIndexes = new int[arr.length];
        int idx = 0;
        for (int key : arr) {
            arrIndexes[idx++] = map.get(key);
        }
 
        BinaryIndexTree bitRightLesser
            = new BinaryIndexTree(arr.length + 1);
        int[] right = new int[n];
        for (int i = n - 1; i >= 0; i--) {
            right[i]
                = bitRightLesser.query(arrIndexes[i] - 1);
            bitRightLesser.update(arrIndexes[i], 1);
        }
 
        for (int i = 0; i < n; i++) {
            arrIndexes[i] = n + 1 - arrIndexes[i];
        }
 
        BinaryIndexTree bitLeftGreater
            = new BinaryIndexTree(arr.length + 1);
        int[] left = new int[n];
        for (int i = 0; i < n; i++) {
            left[i]
                = bitLeftGreater.query(arrIndexes[i] - 1);
            bitLeftGreater.update(arrIndexes[i], 1);
        }
 
        int[] ret = new int[n];
        for (int i = 0; i < n; i++) {
            ret[i] = Math.abs(right[i] - left[i]);
        }
 
        return ret;
    }
 
    // Driver's code
    public static void main(String[] args)
    {
        int[] arr = { 5, 4, 3, 2, 1 };
        int n = arr.length;
 
        // Function call
        int[] ret = retResult(arr, n);
 
        System.out.println(Arrays.toString(ret));
    }
}


Python3




#Python code for the above approach.
class BinaryIndexTree:
    def __init__(self, size):
        # Binary Indexed Tree (Fenwick Tree) initialization.
        self.arr = [0] * (size + 1)
 
    def update(self, x, val):
        # Update the Binary Indexed Tree by adding 'val' to the element at index 'x'.
        if x == 0:
            return
        while x < len(self.arr):
            self.arr[x] += val
            x += x & -x
 
    def query(self, index):
        # Compute the prefix sum of elements from index 1 to 'index'.
        if index == 0:
            return 0
        sum = 0
        while index > 0:
            sum += self.arr[index]
            index -= index & -index
        return sum
 
def ret_result(arr, n):
    # Sort the input array and create a mapping of elements to their sorted order.
    arr_sorted = sorted(arr)
    mapping = {}
    for i, num in enumerate(arr_sorted):
        mapping[num] = i + 1
 
    # Convert the input array to an array of indexes based on their sorted order.
    arr_indexes = [mapping[num] for num in arr]
 
    # Use Binary Indexed Tree to calculate the number of elements greater than the current element on its right.
    bit_right_lesser = BinaryIndexTree(len(arr) + 1)
    right = [0] * n
    for i in range(n - 1, -1, -1):
        right[i] = bit_right_lesser.query(arr_indexes[i] - 1)
        bit_right_lesser.update(arr_indexes[i], 1)
 
    # Update the array of indexes to calculate the number of elements greater than the current element on its left.
    arr_indexes = [n + 1 - num for num in arr_indexes]
 
    # Use Binary Indexed Tree to calculate the number of elements smaller than the current element on its left.
    bit_left_greater = BinaryIndexTree(len(arr) + 1)
    left = [0] * n
    for i in range(n):
        left[i] = bit_left_greater.query(arr_indexes[i] - 1)
        bit_left_greater.update(arr_indexes[i], 1)
 
    # Calculate the absolute difference between the number of elements greater and smaller on both sides for each element.
    ret = [abs(right[i] - left[i]) for i in range(n)]
 
    return ret
 
# Driver's code
if __name__ == "__main__":
    arr = [5, 4, 3, 2, 1]
    n = len(arr)
 
    # Function call to get the resultant array.
    ret = ret_result(arr, n)
 
    # Print the resultant array in the specified format.
    print("[", end="")
    for i in range(len(ret)):
        print(ret[i], end="")
        if i != len(ret) - 1:
            print(", ", end="")
    print("]")
     
# This code is contributed by uttamdp_10


C#




// C# code for the above approach.
using System;
using System.Collections.Generic;
using System.Linq;
 
class GFG {
    // Binary Indexed Tree class.
    class BinaryIndexTree {
        private int[] arr;
 
        public BinaryIndexTree(int size)
        {
            arr = new int[size + 1];
            Array.Fill(arr, 0);
        }
 
        public void update(int x, int val)
        {
            if (x == 0)
                return;
            for (; x < arr.Length; x += x & -x)
                arr[x] += val;
        }
 
        public int query(int index)
        {
            if (index == 0)
                return 0;
            int sum = 0;
            for (; index > 0; index -= index & -index)
                sum += arr[index];
            return sum;
        }
    }
 
    // Function to return the
    // resultant array.
    static int[] retResult(int[] arr, int n)
    {
        int[] arrSorted = arr.ToArray();
        Array.Sort(arrSorted);
 
        Dictionary<int, int> map
            = new Dictionary<int, int>();
        for (int i = 0; i < arrSorted.Length; i++) {
            map.Add(arrSorted[i], i + 1);
        }
 
        int[] arrIndexes = new int[arr.Length];
        int idx = 0;
        foreach(int key in arr)
        {
            arrIndexes[idx++] = map[key];
        }
 
        BinaryIndexTree bitRightLesser
            = new BinaryIndexTree(arr.Length + 1);
        int[] right = new int[n];
        for (int i = n - 1; i >= 0; i--) {
            right[i]
                = bitRightLesser.query(arrIndexes[i] - 1);
            bitRightLesser.update(arrIndexes[i], 1);
        }
 
        for (int i = 0; i < n; i++) {
            arrIndexes[i] = n + 1 - arrIndexes[i];
        }
 
        BinaryIndexTree bitLeftGreater
            = new BinaryIndexTree(arr.Length + 1);
        int[] left = new int[n];
        for (int i = 0; i < n; i++) {
            left[i]
                = bitLeftGreater.query(arrIndexes[i] - 1);
            bitLeftGreater.update(arrIndexes[i], 1);
        }
 
        int[] ret = new int[n];
        for (int i = 0; i < n; i++) {
            ret[i] = Math.Abs(right[i] - left[i]);
        }
 
        return ret;
    }
 
    // Driver's code
    static void Main(string[] args)
    {
        int[] arr = { 5, 4, 3, 2, 1 };
        int n = arr.Length;
 
        // Function call
        int[] ret = retResult(arr, n);
        Console.Write("[");
        Console.Write(string.Join(", ", ret));
        Console.WriteLine("]");
    }
}
 
// This code is contributed by Tapesh(tapeshdua420)


Javascript




// Javascript code for the above approach.
class BinaryIndexTree {
    constructor(size) {
        this.arr = new Array(size + 1).fill(0);
    }
 
    update(x, val) {
        if (x === 0) return;
        for (; x < this.arr.length; x += x & -x)
            this.arr[x] += val;
    }
 
    query(index) {
        if (index === 0) return 0;
        let sum = 0;
        for (; index > 0; index -= index & -index)
            sum += this.arr[index];
        return sum;
    }
}
 
function retResult(arr) {
    const n = arr.length;
    const arrSorted = [...arr].sort((a, b) => a - b);
 
    const map = new Map();
    arrSorted.forEach((value, index) => {
        map.set(value, index + 1);
    });
 
    const arrIndexes = arr.map(value => map.get(value));
 
    const bitRightLesser = new BinaryIndexTree(n + 1);
    const right = new Array(n);
    for (let i = n - 1; i >= 0; i--) {
        right[i] = bitRightLesser.query(arrIndexes[i] - 1);
        bitRightLesser.update(arrIndexes[i], 1);
    }
 
    arrIndexes.forEach((value, index, arr) => {
        arr[index] = n + 1 - value;
    });
 
    const bitLeftGreater = new BinaryIndexTree(n + 1);
    const left = new Array(n);
    for (let i = 0; i < n; i++) {
        left[i] = bitLeftGreater.query(arrIndexes[i] - 1);
        bitLeftGreater.update(arrIndexes[i], 1);
    }
 
    const ret = new Array(n);
    for (let i = 0; i < n; i++) {
        ret[i] = Math.abs(right[i] - left[i]);
    }
 
    return ret;
}
 
// Driver's code
 
    const arr = [5, 4, 3, 2, 1];
 
    // Function call
    const ret = retResult(arr);
 
    console.log('[', ret.join(', '), ']');
}
 
 
//this code is contributed by uttamdp_10


Output

[4, 2, 0, 2, 4]

Time Complexity: O(N * log N)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads