Minimize the size of Array by doing maximum absorptions
Last Updated :
08 Apr, 2022
Given an array A consisting of N integers and an integer K, the task is to minimize the length of array A, by applying absorptions any number of times, such that:
- Any element in A (A[i]) can absorb any other element in A (A[j]), if it is at least K times the other, i.e. A[i] >= K*A[j].
- If an element X is absorbed by any other element Y, then Y is removed from the array and can not be absorbed by any other element. However, the value of X remains the same.
Examples:
Input: N = 8, K = 2, A = {2, 5, 7, 6, 9, 8, 2, 4}
Output: 5
Explanation: Following are the absorptions done and accordingly changes in the array:
{2, 5, 7, 6, 9, 8, 2, 4} -> {5, 7, 6, 9, 8, 2, 4}: 2 is absorbed by 5, as 5>= 2*2
{5, 7, 6, 9, 8, 2, 4} -> {5, 7, 6, 9, 8, 4}: 2 is absorbed by 8, as 8>= 2*2
{5, 7, 6, 9, 8, 4} -> {5, 7, 6, 9, 8}: 4 is absorbed by 9, as 9>=2*4
No further absorptions are possible and final size of the array becomes 5. It can be checked that if absorptions are done in some other way, the size of final array would be more than or equal to 5. Hence, the minimal possible size would be 5.
Input: N=5, K=4, A={10, 11, 12, 13, 14}
Output: 5
Approach: The problem can be solved by a two-pointer approach:
Observations:
- The minimum possible size of final array can be N/2 (the case in which each element either absorbs another element or gets absorbed by another element).
- To perform the absorption process optimally, we can divide the array into two halves such that first half contain smaller elements and second half contains greater elements and greedily perform maximum absorptions.
Follow the below steps to solve this problem:
- Sort the given array.
- Initialize two variables say i and j, that point to first elements of 1st and 2nd half of the array respectively.
- If K times of the element at i is less than the element at j , then decrement the size of the array by 1 (as A[i] would be absorbed by A[j]). Also, increment i and j by 1.
- If not so, that means we need a greater integer to absorb integer at i, so we increment j by 1.
- After completion of iteration, return the size of array.
Following is the code based on above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int minimumSize( int N, int K, int A[])
{
sort(A, A + N);
int i = 0, j = (N + 1) / 2;
int answer = N;
while (i < (N + 1) / 2 && j < N) {
int num1 = A[i];
int num2 = A[j];
if (K * num1 <= num2) {
i++;
j++;
answer--;
}
else {
j++;
}
}
return answer;
}
int main()
{
int N = 8, K = 2;
int A[] = { 2, 5, 7, 6, 9, 8, 2, 4 };
int minimum_size = minimumSize(N, K, A);
cout << minimum_size;
}
|
Java
import java.io.*;
import java.util.Arrays;
class GFG {
static int minimumSize( int N, int K, int A[])
{
Arrays.sort(A);
int i = 0 , j = (N + 1 ) / 2 ;
int answer = N;
while (i < (N + 1 ) / 2 && j < N) {
int num1 = A[i];
int num2 = A[j];
if (K * num1 <= num2) {
i++;
j++;
answer--;
}
else {
j++;
}
}
return answer;
}
public static void main (String[] args) {
int N = 8 , K = 2 ;
int A[] = { 2 , 5 , 7 , 6 , 9 , 8 , 2 , 4 };
int minimum_size = minimumSize(N, K, A);
System.out.println(minimum_size);
}
}
|
Python3
def minimumSize(N, K, A):
A.sort()
i = 0
j = (N + 1 ) / / 2
answer = N
while (i < (N + 1 ) / 2 and j < N):
num1 = A[i]
num2 = A[j]
if K * num1 < = num2:
i + = 1
j + = 1
answer - = 1
else :
j + = 1
return answer
N = 8
K = 2
A = [ 2 , 5 , 7 , 6 , 9 , 8 , 2 , 4 ]
minimum_size = minimumSize(N, K, A)
print (minimum_size)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int minimumSize( int N, int K, int [] A)
{
Array.Sort(A);
int i = 0;
int j = (N + 1) / 2;
int answer = N;
while ((i < (N + 1) / 2) && (j < N))
{
var num1 = A[i];
var num2 = A[j];
if ((K * num1) <= num2)
{
i++;
j++;
answer--;
}
else
j++;
}
return answer;
}
static void Main()
{
var N = 8;
var K = 2;
int [] A = { 2, 5, 7, 6, 9, 8, 2, 4 };
int minimum_size = minimumSize(N, K, A);
Console.Write(minimum_size);
}
}
|
Javascript
<script>
function minimumSize(N, K, A)
{
A.sort( function (a, b) { return a - b })
let i = 0, j = Math.floor((N + 1) / 2);
let answer = N;
while (i < (N + 1) / 2 && j < N)
{
let num1 = A[i];
let num2 = A[j];
if (K * num1 <= num2)
{
i++;
j++;
answer--;
}
else {
j++;
}
}
return answer;
}
let N = 8, K = 2;
let A = [2, 5, 7, 6, 9, 8, 2, 4];
let minimum_size = minimumSize(N, K, A);
document.write(minimum_size);
</script>
|
Time Complexity: O(N*log(N))
Auxiliary Space: O(1)
Share your thoughts in the comments
Please Login to comment...