Open In App

Remove minimum elements from array so that max <= 2 * min

Given an array arr, the task is to remove minimum number of elements such that after their removal, max(arr) <= 2 * min(arr)

Examples:

Input: arr[] = {4, 5, 3, 8, 3} 
Output: 1 Remove 8 from the array. 

Input: arr[] = {1, 2, 3, 4} 
Output: 1 Remove 1 from the array.

Approach: Let us fix each value as the minimum value say x and find number of terms that are in range [x, 2*x]. This can be done using prefix-sums, we can use map (implements self balancing BST) instead of array as the values can be large. The remaining terms which are not in range [x, 2*x] will have to be removed. So, across all values of x, we choose the one which maximises the number of terms in range [x, 2*x].

Below is the implementation of the above approach: 




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to return the minimum removals from
// arr such that max(arr) <= 2 * min(arr)
int minimumRemovals(int n, int a[])
{
    // Count occurrence of each element
    map<int, int> ct;
    for (int i = 0; i < n; i++)
        ct[a[i]]++;
 
    // Take prefix sum
    int sm = 0;
    for (auto mn : ct) {
        sm += mn.second;
        ct[mn.first] = sm;
    }
 
    int mx = 0, prev = 0;
    for (auto mn : ct) {
 
        // Chosen minimum
        int x = mn.first;
        int y = 2 * x;
        auto itr = ct.upper_bound(y);
        itr--;
 
        // Number of elements that are in
        // range [x, 2x]
        int cr = (itr->second) - prev;
        mx = max(mx, cr);
        prev = mn.second;
    }
 
    // Minimum elements to be removed
    return n - mx;
}
 
// Driver Program to test above function
int main()
{
    int arr[] = { 4, 5, 3, 8, 3 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << minimumRemovals(n, arr);
    return 0;
}




// Java implementation of the approach
import java.util.*;
 
public class Main {
    // Function to return the minimum removals from
    // arr such that max(arr) <= 2 * min(arr)
    public static int minimumRemovals(int n, int[] a) {
        // Count occurrence of each element
        Map<Integer, Integer> ct = new HashMap<>();
        for (int i = 0; i < n; i++) {
            ct.put(a[i], ct.getOrDefault(a[i], 0) + 1);
        }
     
        // Take prefix sum
        int sm = 0;
        for (int mn : ct.keySet()) {
            sm += ct.get(mn);
            ct.put(mn, sm);
        }
     
        int mx = 0, prev = 0;
        for (int mn : ct.keySet()) {
            // Chosen minimum
            int x = mn;
            int y = 2 * x;
            List<Integer> keysList = new ArrayList<>(ct.keySet());
            int index = Collections.binarySearch(keysList, y);
            int pos = index >= 0 ? index : -(index + 1) - 1;
            Integer itr = pos >= 0 ? ct.get(keysList.get(pos)) : null;
     
            // Number of elements that are in
            // range [x, 2x]
            int cr = (itr != null ? itr : 0) - prev;
            mx = Math.max(mx, cr);
            prev = ct.get(mn);
        }
     
        // Minimum elements to be removed
        return n - mx;
    }
 
    // Driver Program to test above function
    public static void main(String[] args) {
        int[] arr = { 4, 5, 3, 8, 3 };
        int n = arr.length;
        System.out.println(minimumRemovals(n, arr));
    }
}
 
// This code is contributed by codebraxnzt




# Python3 implementation of the approach
from bisect import bisect_left as upper_bound
 
# Function to return the minimum removals from
# arr such that max(arr) <= 2 * min(arr)
def minimumRemovals(n, a):
     
    # Count occurrence of each element
    ct = dict()
    for i in a:
        ct[i] = ct.get(i, 0) + 1
 
    # Take prefix sum
    sm = 0
    for mn in ct:
        sm += ct[mn]
        ct[mn] = sm
 
    mx = 0
    prev = 0;
    for mn in ct:
 
        # Chosen minimum
        x = mn
        y = 2 * x
        itr = upper_bound(list(ct), y)
 
        # Number of elements that are in
        # range [x, 2x]
        cr = ct[itr] - prev
        mx = max(mx, cr)
        prev = ct[mn]
 
    # Minimum elements to be removed
    return n - mx
 
# Driver Code
arr = [4, 5, 3, 8, 3]
n = len(arr)
print(minimumRemovals(n, arr))
 
# This code is contributed by Mohit Kumar




// C# program for the above approach
 
using System;
using System.Collections.Generic;
 
public class MainClass
{
    // Function to return the minimum removals from
    // arr such that max(arr) <= 2 * min(arr)
    public static int minimumRemovals(int n, int[] a)
    {
        // Count occurrence of each element
        Dictionary<int, int> ct = new Dictionary<int, int>();
        for (int i = 0; i < n; i++)
        {
            if (ct.ContainsKey(a[i]))
            {
                ct[a[i]]++;
            }
            else
            {
                ct[a[i]] = 1;
            }
        }
 
        // Take prefix sum
        int sm = 0;
        List<int> keysList = new List<int>(ct.Keys);
        keysList.Sort();
        foreach (int mn in keysList)
        {
            sm += ct[mn];
            ct[mn] = sm;
        }
 
        int mx = 0, prev = 0;
        foreach (int mn in keysList)
        {
            // Chosen minimum
            int x = mn;
            int y = 2 * x;
 
            int index = keysList.BinarySearch(y);
            int pos = index >= 0 ? index : -(index + 1) - 1;
            int itr = pos >= 0 ? ct[keysList[pos]] : 0;
 
            // Number of elements that are in
            // range [x, 2x]
            int cr = itr - prev;
            mx = Math.Max(mx, cr);
            prev = ct[mn];
        }
 
        // Minimum elements to be removed
        return n - mx;
    }
 
    // Driver Program to test above function
    public static void Main()
    {
        int[] arr = { 4, 5, 3, 8, 3 };
        int n = arr.Length;
        Console.WriteLine(minimumRemovals(n, arr));
    }
}
 
// This code is contributed by Prince Kumar




// JavaScript implementation of the approach
// Function to return the minimum removals from arr such that max(arr) <= 2 * min(arr)
 
function minimumRemovals(n, a){
    // Import upper_bound from bisect
    const upper_bound = (arr, x) => {
        let low = 0, high = arr.length;
        while (low < high) {
            const mid = (low + high) >>> 1;
            if (x >= arr[mid]) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }
   
    // Count occurrence of each element
    let ct = new Map();
    for (let i of a){
        ct.set(i, (ct.get(i) || 0) + 1);
    }
 
    // Take prefix sum
    let sm = 0;
    for (let mn of ct.keys()){
        sm += ct.get(mn);
        ct.set(mn, sm);
    }
 
    let mx = 0;
    let prev = 0;
    for (let mn of ct.keys()){
        // Chosen minimum
        let x = mn;
        let y = 2 * x;
        let itr = upper_bound(Array.from(ct.keys()), y);
 
        // Number of elements that are in range [x, 2x]
        let cr = ct.get([...ct.keys()][itr-1]) - ct.get(mn) + prev;
        mx = Math.max(mx, cr);
        prev = ct.get(mn) - (ct.get(mn - 1) || 0);
    }
 
    // Minimum elements to be removed
    return n - mx;
}
 
// Driver Code
let arr = [4, 5, 3, 8, 3];
let n = arr.length;
console.log(minimumRemovals(n, arr));
 
// This code is contributed by princekumaras

Output
1

Article Tags :