Given an array arr[] of size N. The task is to create a new array result[] of the same size, where result[i] = ∑ |i – j| for all j such that arr[i] = arr[j].
Examples:
Input: arr = {2, 1, 4, 1, 2, 4, 4} Output: {4, 2, 7, 2, 4, 4, 5} Explanation: => 0th Index: Another 2 is found at index 4. |0 – 4| = 4 => 1st Index: Another 1 is found at index 3. |1 – 3| = 2 => 2nd Index: Two more 4s are found at indices 5 and 6. |2 – 5| + |2 – 6| = 7 => 3rd Index: Another 1 is found at index 1. |3 – 1| = 2 => 4th Index: Another 2 is found at index 0. |4 – 0| = 4 => 5th Index: Two more 4s are found at indices 2 and 6. |5 – 2| + |5 – 6| = 4 => 6th Index: Two more 4s are found at indices 2 and 5. |6 – 2| + |6 – 5| = 5
Input: arr = {1, 10, 510, 10} Output: {0, 5, 0, 3, 4}
Constructing an Element Summation Array using Hashing:
To compute result[i], we can apply the following approach:
- Compute leftFreq, the frequency of the same elements to the left of index i.
- Calculate leftSum, the summation of indices where the same element occurs to the left of index i.
- Compute rightSum, the summation of indices where the same element occurs to the right of index i.
- Calculate rightFreq, the frequency of the same elements to the right of index i.
- Compute result[i] using the formula: result[i] = ((leftFreq * i) – leftSum) + (rightSum – (rightFreq * i))
Illustration:
Consider the input arr = {3, 2, 3, 3, 2, 3}
Now, If have to calculate the result for the index i = 3 which is element 3.
- To calculate the absolute value of the required result from the left would be something like => (i – 0) + (i – 2) , which is equals to (2 * i – (0 + 2)).
- To generalise these, we can generate a formula to do the same: (frequency of similar element to the left* i) – (Sum of occurances of such indices).
- To calculate the absolute value of required result from the right would be something like => (5 – i)
- To generalise these, we can generate a formula to do the same: (Sum of occurances of such indices) – (frequency of similar element to the right* i)
- We can conclude from the above that: The result for the ith index would be:
- result[i] = ((leftFreq * i) – leftSum) + (rightSum – (rightFreq * i)).
Step-by-step approach:
- Initialize a map “unmap” of <key, pair<total frequency, total sum>>.
- Initialize another map unmap2 of <key, pair< frequency till any index i, sum till ith index>>.
- Iterate over the given array and update the unmap.
- Create an array result[] for storing the answer
- Iterate over the given array
- Update the result[i] = ((leftFreq * i) – leftSum) + (rightSum – (rightFreq * i)).
- Update the unmap2 by increasing the current element’s frequency and the sum of all occurrences of similar elements till the ith index.
- Finally, return the result[] as the required answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< long long > solve(vector< long long >& arr)
{
int n = arr.size();
unordered_map< int , pair< long long , long long > > unmap,
unmap2;
for ( int i = 0; i < n; i++) {
unmap[arr[i]] = { unmap[arr[i]].first + 1,
unmap[arr[i]].second + i };
}
vector< long long > result(n);
for ( int i = 0; i < n; i++) {
auto curr = unmap2[arr[i]];
long long leftSum = curr.second;
long long leftFreq = curr.first;
long long rightSum
= unmap[arr[i]].second - leftSum - i;
long long rightFreq
= unmap[arr[i]].first - leftFreq - 1;
result[i] = ((leftFreq * i) - leftSum)
+ (rightSum - (rightFreq * i));
unmap2[arr[i]] = { unmap2[arr[i]].first + 1,
unmap2[arr[i]].second + i };
}
return result;
}
int main()
{
vector< long long > arr = { 2, 1, 4, 1, 2, 4, 4 };
vector< long long > result = solve(arr);
for ( auto i : result) {
cout << i << " " ;
}
return 0;
}
|
Java
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class Main {
static Vector<Long> solve(Vector<Long> arr)
{
int n = arr.size();
Map<Long, Pair<Long, Long> > unmap
= new HashMap<>();
Map<Long, Pair<Long, Long> > unmap2
= new HashMap<>();
for ( int i = 0 ; i < n; i++) {
long key = arr.get(i);
Pair<Long, Long> value = unmap.getOrDefault(
key, new Pair<>(0L, 0L));
unmap.put(key, new Pair<>(value.first + 1 ,
value.second + i));
}
Vector<Long> result = new Vector<>(n);
for ( int i = 0 ; i < n; i++) {
long key = arr.get(i);
Pair<Long, Long> curr = unmap2.getOrDefault(
key, new Pair<>(0L, 0L));
long leftSum = curr.second;
long leftFreq = curr.first;
Pair<Long, Long> value = unmap.get(key);
long rightSum = value.second - leftSum - i;
long rightFreq = value.first - leftFreq - 1 ;
result.add(((leftFreq * i) - leftSum)
+ (rightSum - (rightFreq * i)));
unmap2.put(key, new Pair<>(curr.first + 1 ,
curr.second + i));
}
return result;
}
public static void main(String[] args)
{
Vector<Long> arr = new Vector<>();
arr.add(2L);
arr.add(1L);
arr.add(4L);
arr.add(1L);
arr.add(2L);
arr.add(4L);
arr.add(4L);
Vector<Long> result = solve(arr);
for ( long i : result) {
System.out.print(i + " " );
}
}
static class Pair<T, U> {
T first;
U second;
Pair(T first, U second)
{
this .first = first;
this .second = second;
}
}
}
|
Python3
from typing import List , Tuple
def solve(arr: List [ int ]) - > List [ int ]:
n = len (arr)
unmap = {}
unmap2 = {}
for i in range (n):
key = arr[i]
value = unmap.get(key, ( 0 , 0 ))
unmap[key] = (value[ 0 ] + 1 , value[ 1 ] + i)
result = []
for i in range (n):
key = arr[i]
curr = unmap2.get(key, ( 0 , 0 ))
leftSum, leftFreq = curr[ 1 ], curr[ 0 ]
value = unmap[key]
rightSum = value[ 1 ] - leftSum - i
rightFreq = value[ 0 ] - leftFreq - 1
result.append(((leftFreq * i) - leftSum) + (rightSum - (rightFreq * i)))
unmap2[key] = (curr[ 0 ] + 1 , curr[ 1 ] + i)
return result
if __name__ = = "__main__" :
arr = [ 2 , 1 , 4 , 1 , 2 , 4 , 4 ]
result = solve(arr)
print ( * result)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public static List< long > Solve(List< long > arr)
{
int n = arr.Count;
var unmap = new Dictionary< long , Tuple< long , long >>();
var unmap2 = new Dictionary< long , Tuple< long , long >>();
for ( int i = 0; i < n; i++)
{
long key = arr[i];
if (!unmap.TryGetValue(key, out var value))
{
value = new Tuple< long , long >(0, 0);
}
unmap[key] = new Tuple< long , long >(value.Item1 + 1, value.Item2 + i);
}
List< long > result = new List< long >();
for ( int i = 0; i < n; i++)
{
long key = arr[i];
if (!unmap2.TryGetValue(key, out var curr))
{
curr = new Tuple< long , long >(0, 0);
}
long leftSum = curr.Item2;
long leftFreq = curr.Item1;
var value = unmap[key];
long rightSum = value.Item2 - leftSum - i;
long rightFreq = value.Item1 - leftFreq - 1;
result.Add(((leftFreq * i) - leftSum) + (rightSum - (rightFreq * i)));
unmap2[key] = new Tuple< long , long >(curr.Item1 + 1, curr.Item2 + i);
}
return result;
}
static void Main( string [] args)
{
List< long > arr = new List< long > { 2, 1, 4, 1, 2, 4, 4 };
List< long > result = Solve(arr);
foreach ( var item in result)
{
Console.Write(item + " " );
}
}
}
|
Javascript
function solve(arr) {
const n = arr.length;
const unmap = new Map();
const unmap2 = new Map();
for (let i = 0; i < n; i++) {
const key = arr[i];
if (!unmap.has(key)) {
unmap.set(key, [0, 0]);
}
const [freq, sum] = unmap.get(key);
unmap.set(key, [freq + 1, sum + i]);
}
const result = [];
for (let i = 0; i < n; i++) {
const key = arr[i];
const curr = unmap2.get(key) || [0, 0];
const leftSum = curr[1];
const leftFreq = curr[0];
const [freq, sum] = unmap.get(key);
const rightSum = sum - leftSum - i;
const rightFreq = freq - leftFreq - 1;
result.push((leftFreq * i) - leftSum + rightSum - (rightFreq * i));
unmap2.set(key, [curr[0] + 1, curr[1] + i]);
}
return result;
}
const arr = [2, 1, 4, 1, 2, 4, 4];
const result = solve(arr);
console.log(result.join(' '));
|
Time Complexity: O(N) Auxiliary space: O(N)
|