Open In App

Maximum distinct elements after removing k elements

Last Updated : 06 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array arr[] containing n elements. The task is to find the maximum count of distinct elements (non-repeating) after removing k elements from the array. 

Note: 1 <= k <= n.

Examples: 

Input : arr[] = [5, 7, 5, 5, 1, 2, 2], k = 3
Output : 4
Explanation: Remove 2 occurrences of element 5 and 1 occurrence of element 2.

Input : arr[] = [1, 2, 3, 4, 5, 6, 7], k = 5
Output : 2
Explanation: Remove any 5 numbers

Input : arr[] = [1, 2, 2, 2], k = 1
Output : 1
Explanation: Remove 1 occurrence of 2. Array will become [1, 2, 2]. Here 1 and 2 are the two distinct values.

Using Hash Map and Max Heap - O(n * log n) time and O(n) space

The idea is to maximize the number of distinct elements after removing k elements by first reducing the frequency of duplicate prioritizing elements with the highest frequency (using a max heap), and then adjusting for any remaining removals.

Step by step approach:

  1. Use a hash map to count the frequency of each element in the array.
  2. While the heap is not empty, remove the element with the highest frequency:
    1. For each element, reduce its frequency by min(freq-1, k) to eliminate duplicates and decrement k accordingly.
    2. Increment the distinct count for each processed element.
  3. If k > 0 after processing all elements, subtract k from the distinct count to account for removing unique elements.
  4. Return the final count of distinct elements.
C++
// C++ program to find maximum distinct 
// elements after removing k elements
#include <bits/stdc++.h> 
using namespace std; 
  
// function to find maximum distinct elements 
// after removing k elements 
int maxDistinctNum(vector<int> &arr, int k) {
    
    // Map to store the count of each 
    // value present in the array.
    unordered_map<int,int> map;
    
    for (int val: arr) {
        map[val]++;
    }
    
    // Max heap in order of higher
    // frequency.
    priority_queue<pair<int,int>> pq;
    
    // Traverse the map and value and 
    // its frequency into the heap 
    for (auto p: map) {
        int val = p.first;
        int freq = p.second;
        
        pq.push({freq, val});
    }
    
    int ans = 0;
    
    while (!pq.empty()) {
        
        pair<int,int> top = pq.top();
        pq.pop();
        int val = top.second;
        int freq = top.first;
        
        // Remove min(freq-1, k) occurrences
        // of val
        int toRemove = min(freq-1, k);
        
        // Increment the distinct count.
        ans++;
        
        // Decrement k.
        k -= toRemove;
    }
 
    // If k > 0, we need to remove 
    // k distinct values.
    return ans-k;
    
}

int main()  { 
    vector<int> arr = {5, 7, 5, 5, 1, 2, 2}; 
    int k = 3; 
  
    cout << maxDistinctNum(arr, k) << endl; 
    return 0; 
} 
Java
// Java program to find maximum distinct 
// elements after removing k elements
import java.util.*;

class GfG {

    // function to find maximum distinct elements 
    // after removing k elements 
    static int maxDistinctNum(int[] arr, int k) {
        
        // Map to store the count of each 
        // value present in the array.
        HashMap<Integer, Integer> map = new HashMap<>();
        
        for (int val : arr) {
            map.put(val, map.getOrDefault(val, 0) + 1);
        }
        
        // Max heap in order of higher
        // frequency.
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> b[0] - a[0]);
        
        // Traverse the map and value and 
        // its frequency into the heap 
        for (Map.Entry<Integer, Integer> p : map.entrySet()) {
            int val = p.getKey();
            int freq = p.getValue();
            pq.add(new int[]{freq, val});
        }
        
        int ans = 0;
        
        while (!pq.isEmpty()) {
            
            int[] top = pq.poll();
            int val = top[1];
            int freq = top[0];
            
            // Remove min(freq-1, k) occurrences
            // of val
            int toRemove = Math.min(freq - 1, k);
            
            // Increment the distinct count.
            ans++;
            
            // Decrement k.
            k -= toRemove;
        }
    
        // If k > 0, we need to remove 
        // k distinct values.
        return ans - k;
    }

    public static void main(String[] args) {
        int[] arr = {5, 7, 5, 5, 1, 2, 2};
        int k = 3;
    
        System.out.println(maxDistinctNum(arr, k));
    }
}
Python
# Python program to find maximum distinct 
# elements after removing k elements

import heapq
from collections import Counter

# function to find maximum distinct elements 
# after removing k elements 
def maxDistinctNum(arr, k):
    
    # Map to store the count of each 
    # value present in the array.
    map = Counter(arr)
    
    # Max heap in order of higher
    # frequency.
    pq = []
    
    # Traverse the map and value and 
    # its frequency into the heap 
    for val, freq in map.items():
        heapq.heappush(pq, (-freq, val))
    
    ans = 0
    
    while pq:
        
        freq, val = heapq.heappop(pq)
        freq = -freq  # Convert back to positive
        
        # Remove min(freq-1, k) occurrences
        # of val
        toRemove = min(freq - 1, k)
        
        # Increment the distinct count.
        ans += 1
        
        # Decrement k.
        k -= toRemove

    # If k > 0, we need to remove 
    # k distinct values.
    return ans - k

if __name__ == "__main__":
    arr = [5, 7, 5, 5, 1, 2, 2]
    k = 3

    print(maxDistinctNum(arr, k))
C#
// C# program to find maximum distinct
// elements after removing k elements
using System;
using System.Collections.Generic;

class GfG {
    
    // Function to find maximum distinct elements
    // after removing k elements
    static int maxDistinctNum(int[] arr, int k) {
        
        // Map to store the count of each 
        // value present in the array.
        Dictionary<int, int> map = new Dictionary<int, int>();

        foreach (int val in arr) {
            if (map.ContainsKey(val))
                map[val]++;
            else
                map[val] = 1;
        }
        
        // Max heap in order of higher
        // frequency.
        PriorityQueue<Pair> pq = new PriorityQueue<Pair>(new Comparer());
        
        // Traverse the map and value and 
        // its frequency into the heap 
        foreach (var p in map) {
            int val = p.Key;
            int freq = p.Value;
            pq.Enqueue(new Pair(freq, val));
        }

        int ans = 0;

        while (pq.Count > 0) {
            Pair top = pq.Dequeue();
            int freq = top.first;
            
            // Remove min(freq-1, k) occurrences
            // of val
            int toRemove = Math.Min(freq - 1, k);
            
            // Increment the distinct count.
            ans++;
            
            // Decrement k.
            k -= toRemove;
        }
        
        // If k > 0, we need to remove 
        // k distinct values.
        return ans - k;
    }

    static void Main() {
        int[] arr = { 5, 7, 5, 5, 1, 2, 2 };
        int k = 3;

        Console.WriteLine(maxDistinctNum(arr, k));
    }
}

class Pair {
    public int first, second;
    public Pair(int f, int s) {
        first = f;
        second = s;
    }
}

// Custom comparator class for max heap
class Comparer : IComparer<Pair> {
    public int Compare(Pair a, Pair b) {
        return a.first - b.first; 
    }
}

class PriorityQueue<T> {
    private List<T> heap;
    private IComparer<T> comparer;

    public PriorityQueue(IComparer<T> comparer) {
        this.heap = new List<T>();
        this.comparer = comparer;
    }

    public int Count => heap.Count;

    public void Enqueue(T item) {
        heap.Add(item);
        int i = heap.Count - 1;
        while (i > 0) {
            int parent = (i - 1) / 2;
            if (comparer.Compare(heap[parent], heap[i]) >= 0)
                break;
            Swap(parent, i);
            i = parent;
        }
    }

    public T Dequeue() {
        if (heap.Count == 0)
            throw new InvalidOperationException("Priority queue is empty.");
        T result = heap[0];
        int last = heap.Count - 1;
        heap[0] = heap[last];
        heap.RemoveAt(last);
        last--;
        int i = 0;
        while (true) {
            int left = 2 * i + 1;
            if (left > last)
                break;
            int right = left + 1;
            int maxChild = left;
            if (right <= last && comparer.Compare(heap[right], heap[left]) > 0)
                maxChild = right;
            if (comparer.Compare(heap[i], heap[maxChild]) >= 0)
                break;
            Swap(i, maxChild);
            i = maxChild;
        }
        return result;
    }

    private void Swap(int i, int j) {
        T temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
}
JavaScript
// JavaScript program to find maximum distinct 
// elements after removing k elements

// Comparator function for max heap
function Comparator(k1, k2) {
    return k2[0] - k1[0]; 
}

class PriorityQueue {
	constructor(compare) {
		this.heap = [];
		this.compare = compare;
	}

	enqueue(value) {
		this.heap.push(value);
		this.bubbleUp();
	}

	bubbleUp() {
		let index = this.heap.length - 1;
		while (index > 0) {
			let element = this.heap[index],
			    parentIndex = Math.floor((index - 1) / 2),
			    parent = this.heap[parentIndex];
			if (this.compare(element, parent) < 0) break;
			this.heap[index] = parent;
			this.heap[parentIndex] = element;
			index = parentIndex;
		}
	}

	dequeue() {
		let max = this.heap[0];
		let end = this.heap.pop();
		if (this.heap.length > 0) {
			this.heap[0] = end;
			this.sinkDown(0);
		}
		return max;
	}

	sinkDown(index) {
		let left = 2 * index + 1,
		    right = 2 * index + 2,
		    largest = index;

		if (
		    left < this.heap.length &&
		    this.compare(this.heap[left], this.heap[largest]) > 0
		) {
			largest = left;
		}

		if (
		    right < this.heap.length &&
		    this.compare(this.heap[right], this.heap[largest]) > 0
		) {
			largest = right;
		}

		if (largest !== index) {
			[this.heap[largest], this.heap[index]] = [
			            this.heap[index],
			            this.heap[largest],
			        ];
			this.sinkDown(largest);
		}
	}

	isEmpty() {
		return this.heap.length === 0;
	}
}


function maxDistinctNum(arr, k) {
    let map = new Map();
    arr.forEach(val => map.set(val, (map.get(val) || 0) + 1));
    
    let pq = new PriorityQueue(Comparator);
    map.forEach((freq, val) => pq.enqueue([freq, val]));

    let ans = 0;

    while (pq.heap.length) {
        let [freq, val] = pq.dequeue();
        let toRemove = Math.min(freq - 1, k);
        ans++;
        k -= toRemove;
    }

    return ans - k;
}

console.log(maxDistinctNum([5, 7, 5, 5, 1, 2, 2], 3));

Output
4

Using Hash Set - O(n) time and O(n) space

The idea is based on the fact that removing duplicate entries does not change the result as long as we can. So we first try removing duplicates and then adjust the result by removing unique elements.

Step by step approach:

  1. Initialize an empty set to store distinct elements.
  2. Iterate through each element in the array.
    1. If the element is already in the set and k > 0, decrement k (remove the duplicate).
    2. If the element is not in the set, add it to the set.
  3. After processing all elements, if k > 0, subtract k from the size of the set (remove remaining unique elements).
  4. Return the size of the set minus any remaining k as the result.
C++
// C++ program to find maximum distinct 
// elements after removing k elements
#include <bits/stdc++.h> 
using namespace std; 
  
// function to find maximum distinct elements 
// after removing k elements 
int maxDistinctNum(vector<int> &arr, int k) {
    
    // Set to check if a value is 
    // already present or not. 
    unordered_set<int> set;
    
    for (int i=0; i<arr.size(); i++) {
        
        // If value is already present in set 
        // and k > 0, decrement value of k.
        if (set.find(arr[i])!=set.end()&&k>0) {
            k--;
        }
        
        // Else add the value to set 
        else {
            set.insert(arr[i]);
        }
    }
    
    // Set contains all the distinct values
    // If k > 0, we still need to remove k 
    // distinct values. Distinct values left 
    // will be equal to size of set minus k.
    return set.size()-k;
}

int main()  { 
    vector<int> arr = { 5, 7, 5, 5, 1, 2, 2 }; 
    int k = 3; 
  
    cout << maxDistinctNum(arr, k) << endl; 
    return 0; 
} 
Java
// Java program to find maximum distinct 
// elements after removing k elements

import java.util.HashSet;

class GfG {
    
    // function to find maximum distinct elements 
    // after removing k elements 
    static int maxDistinctNum(int[] arr, int k) {
        
        // Set to check if a value is 
        // already present or not. 
        HashSet<Integer> set = new HashSet<>();
        
        for (int i = 0; i < arr.length; i++) {
            
            // If value is already present in set 
            // and k > 0, decrement value of k.
            if (set.contains(arr[i]) && k > 0) {
                k--;
            }
            
            // Else add the value to set 
            else {
                set.add(arr[i]);
            }
        }
        
        // Set contains all the distinct values
        // If k > 0, we still need to remove k 
        // distinct values. Distinct values left 
        // will be equal to size of set minus k.
        return set.size() - k;
    }

    public static void main(String[] args) {
        int[] arr = { 5, 7, 5, 5, 1, 2, 2 }; 
        int k = 3; 

        System.out.println(maxDistinctNum(arr, k));
    }
}
Python
# Python program to find maximum distinct 
# elements after removing k elements

# function to find maximum distinct elements 
# after removing k elements 
def maxDistinctNum(arr, k):
    
    # Set to check if a value is 
    # already present or not. 
    uniqSet = set()
    
    for num in arr:
        
        # If value is already present in set 
        # and k > 0, decrement value of k.
        if num in uniqSet and k > 0:
            k -= 1
        
        # Else add the value to set 
        else:
            uniqSet.add(num)
    
    # Set contains all the distinct values
    # If k > 0, we still need to remove k 
    # distinct values. Distinct values left 
    # will be equal to size of set minus k.
    return len(uniqSet) - k

if __name__ == "__main__":
    arr = [5, 7, 5, 5, 1, 2, 2] 
    k = 3 

    print(maxDistinctNum(arr, k))
C#
// C# program to find maximum distinct 
// elements after removing k elements

using System;
using System.Collections.Generic;

class GfG {
    
    // function to find maximum distinct elements 
    // after removing k elements 
    static int maxDistinctNum(int[] arr, int k) {
        
        // Set to check if a value is 
        // already present or not. 
        HashSet<int> set = new HashSet<int>();
        
        for (int i = 0; i < arr.Length; i++) {
            
            // If value is already present in set 
            // and k > 0, decrement value of k.
            if (set.Contains(arr[i]) && k > 0) {
                k--;
            }
            
            // Else add the value to set 
            else {
                set.Add(arr[i]);
            }
        }
        
        // Set contains all the distinct values
        // If k > 0, we still need to remove k 
        // distinct values. Distinct values left 
        // will be equal to size of set minus k.
        return set.Count - k;
    }

    static void Main() {
        int[] arr = { 5, 7, 5, 5, 1, 2, 2 }; 
        int k = 3; 

        Console.WriteLine(maxDistinctNum(arr, k));
    }
}
JavaScript
// JavaScript program to find maximum distinct 
// elements after removing k elements

// function to find maximum distinct elements 
// after removing k elements 
function maxDistinctNum(arr, k) {
    
    // Set to check if a value is 
    // already present or not. 
    let set = new Set();
    
    for (let i = 0; i < arr.length; i++) {
        
        // If value is already present in set 
        // and k > 0, decrement value of k.
        if (set.has(arr[i]) && k > 0) {
            k--;
        }
        
        // Else add the value to set 
        else {
            set.add(arr[i]);
        }
    }
    
    // Set contains all the distinct values
    // If k > 0, we still need to remove k 
    // distinct values. Distinct values left 
    // will be equal to size of set minus k.
    return set.size - k;
}

let arr = [5, 7, 5, 5, 1, 2, 2]; 
let k = 3; 

console.log(maxDistinctNum(arr, k));

Output
4

Next Article
Article Tags :
Practice Tags :

Similar Reads