Given an array of arr[] of positive integers that may contain many repeating elements, the task is to find the maximum difference in frequency between any two distinct elements. The element with the higher frequency must also have a greater value than the lower frequency element. Mathematically, we need to find the maximum possible difference between the frequencies of any two distinct elements arr[i] and arr[j], such that:
- freq(arr[i]) - freq(arr[j]) is maximized
- freq(arr[i]) > freq(arr[j])
- arr[i] > arr[j]
Examples:
Input: [3, 1, 3, 3, 5, 5, 2, 2]
Output: 2
Explanation: 3 appears 3 times and 1 appears 1 time. Clearly freq(3) > freq(1). Also 3 > 1.
Difference in frequencies = freq(3) - freq(1) => 3 - 1 = 2Input: [7, 8, 7, 8, 8]
Output: 1
Explanation: 8 appears 3 times and 7 appears 2 times. Clearly freq(8) > freq(7). Also 8 > 7.
Difference in frequencies = freq(8) - freq(7) => 3 - 2 = 1Input: [10, 10, 10, 5, 5, 5, 5, 7]
Output: 2
Table of Content
[Naive Approach] Using Hashing - O(n^2) Time and O(n) Space
The idea is to use hashing to count the frequency of each unique element in the array. Then, by checking all pairs of elements, we identify those where one element has both a greater value and a higher frequency than the other. For such valid pairs, we compute the difference in frequency and keep track of the maximum. The approach is based on the observation that both conditions, greater value and higher frequency must hold simultaneously for a valid comparison.
// C++ program to find maximum difference
// between frequency of two elements in an
// array using Hashing
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
int maxFrequencyDiff(vector<int>& arr) {
// Frequency map to store count
// of each element
unordered_map<int, int> freq;
// Count frequencies
for (int x : arr) {
freq[x]++;
}
int maxDiff = 0;
// Compare each pair of distinct elements
for (auto& a : freq) {
for (auto& b : freq) {
// Ensure a has higher value and higher
// frequency than b
if (a.first > b.first && a.second > b.second) {
int diff = a.second - b.second;
maxDiff = max(maxDiff, diff);
}
}
}
return maxDiff;
}
int main() {
vector<int> arr = {3, 1, 3, 3, 5, 5, 2, 2};
cout << maxFrequencyDiff(arr);
return 0;
}
// Java program to find maximum difference
// between frequency of two elements in an
// array using Hashing
import java.util.*;
class GfG {
public static int maxFrequencyDiff(int[] arr) {
// Frequency map to store count
// of each element
HashMap<Integer, Integer> freq = new HashMap<>();
// Count frequencies
for (int x : arr) {
freq.put(x, freq.getOrDefault(x, 0) + 1);
}
int maxDiff = 0;
// Compare each pair of distinct elements
for (Map.Entry<Integer, Integer> a : freq.entrySet()) {
for (Map.Entry<Integer, Integer> b : freq.entrySet()) {
// Ensure a has higher value and higher
// frequency than b
if (a.getKey() > b.getKey() && a.getValue() > b.getValue()) {
int diff = a.getValue() - b.getValue();
maxDiff = Math.max(maxDiff, diff);
}
}
}
return maxDiff;
}
public static void main(String[] args) {
int[] arr = {3, 1, 3, 3, 5, 5, 2, 2};
System.out.println(maxFrequencyDiff(arr));
}
}
# Python program to find maximum difference
# between frequency of two elements in an
# array using Hashing
from collections import defaultdict
def maxFrequencyDiff(arr):
# Frequency map to store count
# of each element
freq = defaultdict(int)
# Count frequencies
for x in arr:
freq[x] += 1
maxDiff = 0
# Compare each pair of distinct elements
for aKey, aVal in freq.items():
for bKey, bVal in freq.items():
# Ensure a has higher value and higher
# frequency than b
if aKey > bKey and aVal > bVal:
diff = aVal - bVal
maxDiff = max(maxDiff, diff)
return maxDiff
if __name__ == "__main__":
arr = [3, 1, 3, 3, 5, 5, 2, 2]
print(maxFrequencyDiff(arr))
// C# program to find maximum difference
// between frequency of two elements in an
// array using Hashing
using System;
using System.Collections.Generic;
class GfG {
public static int maxFrequencyDiff(int[] arr) {
// Frequency map to store count
// of each element
Dictionary<int, int> freq = new Dictionary<int, int>();
// Count frequencies
foreach (int x in arr) {
if (freq.ContainsKey(x)) {
freq[x]++;
} else {
freq[x] = 1;
}
}
int maxDiff = 0;
// Compare each pair of distinct elements
foreach (var a in freq) {
foreach (var b in freq) {
// Ensure a has higher value and higher
// frequency than b
if (a.Key > b.Key && a.Value > b.Value) {
int diff = a.Value - b.Value;
maxDiff = Math.Max(maxDiff, diff);
}
}
}
return maxDiff;
}
static void Main() {
int[] arr = {3, 1, 3, 3, 5, 5, 2, 2};
Console.WriteLine(maxFrequencyDiff(arr));
}
}
// JavaScript program to find maximum difference
// between frequency of two elements in an
// array using Hashing
function maxFrequencyDiff(arr) {
// Frequency map to store count
// of each element
let freq = new Map();
// Count frequencies
for (let x of arr) {
freq.set(x, (freq.get(x) || 0) + 1);
}
let maxDiff = 0;
// Compare each pair of distinct elements
for (let [aKey, aVal] of freq.entries()) {
for (let [bKey, bVal] of freq.entries()) {
// Ensure a has higher value and higher
// frequency than b
if (aKey > bKey && aVal > bVal) {
let diff = aVal - bVal;
maxDiff = Math.max(maxDiff, diff);
}
}
}
return maxDiff;
}
// Driver Code
let arr = [3, 1, 3, 3, 5, 5, 2, 2];
console.log(maxFrequencyDiff(arr));
Output
2
[Expected Approach] Using Hashing + Sorting - O(n*log(n)) Time and O(n) Space
The idea is to optimize the previous approach by reducing redundant comparisons using sorting. We first hash the frequencies and extract all distinct elements. We then sort the distinct elements to ensure increasing order as it ensures we only consider valid element pairs where the larger value comes after the smaller one. For each element, we track the minimum frequency so far and compute the difference if the current frequency is greater.
Steps to implement the above idea:
- Create a frequency map using hashing to count occurrences of each element in the input array.
- Extract all distinct elements from the frequency map into a separate array.
- Sort the distinct elements in increasing order to ensure the higher values appear after smaller ones.
- Initialize a variable to track the minimum frequency seen so far, starting with the frequency of the first element.
- Iterate through the sorted list starting from the second element and fetch its current frequency from the map.
- If the current frequency is greater than the minimum so far, update maximum difference accordingly.
- After each step, update the minimum frequency seen so far using the smaller of current and previous minimum.
// C++ program to find maximum difference
// between frequency of two elements in an
// array using Hashing + Sorting
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
int maxFrequencyDiff(vector<int>& arr) {
// Frequency map to store count
// of each element
unordered_map<int, int> freq;
// Count frequencies
for (int x : arr) {
freq[x]++;
}
// Extract all distinct elements
vector<int> dist;
for (auto& entry : freq) {
dist.push_back(entry.first);
}
// Sort distinct elements
sort(dist.begin(), dist.end());
int maxDiff = 0;
// Track minimum frequency so far
int minFreqSoFar = freq[dist[0]];
for (int i = 1; i < dist.size(); i++) {
int currFreq = freq[dist[i]];
// Ensure current frequency is greater
if (currFreq > minFreqSoFar) {
maxDiff = max(maxDiff,
currFreq - minFreqSoFar);
}
// Update the minimum frequency so far
minFreqSoFar = min(minFreqSoFar, currFreq);
}
return maxDiff;
}
int main() {
vector<int> arr = {3, 1, 3, 3, 5, 5, 2, 2};
cout << maxFrequencyDiff(arr);
return 0;
}
// Java program to find maximum difference
// between frequency of two elements in an
// array using Hashing + Sorting
import java.util.*;
class GfG {
static int maxFrequencyDiff(int[] arr) {
// Frequency map to store count
// of each element
HashMap<Integer, Integer> freq = new HashMap<>();
// Count frequencies
for (int x : arr) {
freq.put(x, freq.getOrDefault(x, 0) + 1);
}
// Extract all distinct elements
List<Integer> dist = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
dist.add(entry.getKey());
}
// Sort distinct elements
Collections.sort(dist);
int maxDiff = 0;
// Track minimum frequency so far
int minFreqSoFar = freq.get(dist.get(0));
for (int i = 1; i < dist.size(); i++) {
int currFreq = freq.get(dist.get(i));
// Ensure current frequency is greater
if (currFreq > minFreqSoFar) {
maxDiff = Math.max(maxDiff,
currFreq - minFreqSoFar);
}
// Update the minimum frequency so far
minFreqSoFar = Math.min(minFreqSoFar, currFreq);
}
return maxDiff;
}
public static void main(String[] args) {
int[] arr = {3, 1, 3, 3, 5, 5, 2, 2};
System.out.println(maxFrequencyDiff(arr));
}
}
# Python program to find maximum difference
# between frequency of two elements in an
# array using Hashing + Sorting
from collections import Counter
def maxFrequencyDiff(arr):
# Frequency map to store count
# of each element
freq = Counter(arr)
# Extract all distinct elements
dist = list(freq.keys())
# Sort distinct elements
dist.sort()
maxDiff = 0
# Track minimum frequency so far
minFreqSoFar = freq[dist[0]]
for i in range(1, len(dist)):
currFreq = freq[dist[i]]
# Ensure current frequency is greater
if currFreq > minFreqSoFar:
maxDiff = max(maxDiff,
currFreq - minFreqSoFar)
# Update the minimum frequency so far
minFreqSoFar = min(minFreqSoFar, currFreq)
return maxDiff
if __name__ == "__main__":
arr = [3, 1, 3, 3, 5, 5, 2, 2]
print(maxFrequencyDiff(arr))
// C# program to find maximum difference
// between frequency of two elements in an
// array using Hashing + Sorting
using System;
using System.Collections.Generic;
class GfG {
static int maxFrequencyDiff(int[] arr) {
// Frequency map to store count
// of each element
Dictionary<int, int> freq = new Dictionary<int, int>();
// Count frequencies
foreach (int x in arr) {
if (!freq.ContainsKey(x)) {
freq[x] = 0;
}
freq[x]++;
}
// Extract all distinct elements
List<int> dist = new List<int>();
foreach (var entry in freq) {
dist.Add(entry.Key);
}
// Sort distinct elements
dist.Sort();
int maxDiff = 0;
// Track minimum frequency so far
int minFreqSoFar = freq[dist[0]];
for (int i = 1; i < dist.Count; i++) {
int currFreq = freq[dist[i]];
// Ensure current frequency is greater
if (currFreq > minFreqSoFar) {
maxDiff = Math.Max(maxDiff,
currFreq - minFreqSoFar);
}
// Update the minimum frequency so far
minFreqSoFar = Math.Min(minFreqSoFar, currFreq);
}
return maxDiff;
}
static void Main() {
int[] arr = {3, 1, 3, 3, 5, 5, 2, 2};
Console.WriteLine(maxFrequencyDiff(arr));
}
}
// JavaScript program to find maximum difference
// between frequency of two elements in an
// array using Hashing + Sorting
function maxFrequencyDiff(arr) {
// Frequency map to store count
// of each element
const freq = new Map();
// Count frequencies
for (const x of arr) {
freq.set(x, (freq.get(x) || 0) + 1);
}
// Extract all distinct elements
const dist = Array.from(freq.keys());
// Sort distinct elements
dist.sort((a, b) => a - b);
let maxDiff = 0;
// Track minimum frequency so far
let minFreqSoFar = freq.get(dist[0]);
for (let i = 1; i < dist.length; i++) {
const currFreq = freq.get(dist[i]);
// Ensure current frequency is greater
if (currFreq > minFreqSoFar) {
maxDiff = Math.max(maxDiff,
currFreq - minFreqSoFar);
}
// Update the minimum frequency so far
minFreqSoFar = Math.min(minFreqSoFar, currFreq);
}
return maxDiff;
}
// Driver Code
const arr = [3, 1, 3, 3, 5, 5, 2, 2];
console.log(maxFrequencyDiff(arr));
Output
2