Given an integer array arr[] of size N and a positive integer K, the task is to minimize the maximum of the array by replacing any element arr[i] into two positive elements (X, Y) at most K times such that arr[i] = X + Y.
Examples:
Input: arr = {9}, K = 2 Output: 3 Explanation: Operation 1: Replace element 9 into {6, 3} then array becomes {6, 3}. Operation 2: Replace element 6 into {3, 3} then array becomes {3, 3, 3}. So, the maximum element in arr[] after performing at most K operations are 3.
Input: arr = {2, 4, 8, 2}, K = 4 Output: 2
The problem can be solved using binary search based on the following idea:
Initialize start with minimum possible answer and end with maximum possible answer, then calculate the threshold value mid = (start + end) /2 and check if it is possible to make every element less than or equals to mid in at most K operations. If it is possible, update the result and shift end of range to mid – 1. Otherwise, shift start of range to mid + 1.
Follow the steps below to implement the above idea:
- Initialize a variable start = 1 and end = maximum possible answer.
- Initialize a variable result that will store the answer
- While start ? end
- Calculate mid = (start + end) / 2
- Calculate the maximum number of operations required to make every element less than or equal to mid.
- Iterate over the given array
- Check if the current element is greater than mid
- If true, then calculate the operation required to make this element less than or equals to mid
- Check if the total operation required to make every element less than or equal to mid is greater less than equal to K
- If true, update the result and move the end to mid – 1
- Otherwise, move the start to mid + 1.
- Return the result.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int minimizeMaxElement(vector< int >& arr, int K)
{
int start = 1,
end = *max_element(arr.begin(), arr.end());
int result = -1;
while (start <= end) {
int mid = (start + end) >> 1;
int operation = 0;
for ( int i = 0; i < arr.size(); i++) {
if (arr[i] > mid) {
operation += ceil (( double )arr[i] / mid) - 1;
}
}
if (operation <= K) {
result = mid;
end = mid - 1;
}
else {
start = mid + 1;
}
}
return result;
}
int main()
{
vector< int > arr = { 2, 4, 8, 2 };
int K = 4;
cout << minimizeMaxElement(arr, K);
return 0;
}
|
Java
import java.io.*;
public class GFG {
static int minimizeMaxElement( int []arr, int K)
{
int start = 1 ;
int max = 0 ;
for ( int i= 0 ; i<arr.length; i++ ) {
if (arr[i]>max) {
max = arr[i];
}
}
int end = max;
int result = - 1 ;
while (start <= end) {
int mid = (start + end) >> 1 ;
int operation = 0 ;
for ( int i = 0 ; i < arr.length; i++) {
if (arr[i] > mid) {
operation += Math.ceil(( double )arr[i] / mid) - 1 ;
}
}
if (operation <= K) {
result = mid;
end = mid - 1 ;
}
else {
start = mid + 1 ;
}
}
return result;
}
public static void main (String[] args) {
int []arr = { 2 , 4 , 8 , 2 };
int K = 4 ;
System.out.println(minimizeMaxElement(arr, K));
}
}
|
Python3
from math import *
def minimizeMaxElement(arr, K) :
start = 1 ;
end = max (arr)
result = - 1 ;
while (start < = end) :
mid = (start + end) >> 1 ;
operation = 0 ;
for i in range ( len (arr)) :
if (arr[i] > mid) :
operation + = ceil(arr[i] / mid) - 1 ;
if (operation < = K) :
result = mid;
end = mid - 1 ;
else :
start = mid + 1 ;
return result;
if __name__ = = "__main__" :
arr = [ 2 , 4 , 8 , 2 ];
K = 4 ;
print (minimizeMaxElement(arr, K));
|
C#
using System;
class GFG {
static int minimizeMaxElement( int [] arr, int K)
{
int start = 1;
int max = 0;
for ( int i = 0; i < arr.Length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
int end = max;
int result = -1;
while (start <= end) {
int mid = (start + end) >> 1;
double operation = 0;
for ( int i = 0; i < arr.Length; i++) {
if (arr[i] > mid) {
operation
+= Math.Ceiling(( float )arr[i] / mid)
- 1;
}
}
if (operation <= K) {
result = mid;
end = mid - 1;
}
else {
start = mid + 1;
}
}
return result;
}
public static void Main()
{
int [] arr = { 2, 4, 8, 2 };
int K = 4;
Console.WriteLine(minimizeMaxElement(arr, K));
}
}
|
Javascript
function minimizeMaxElement(arr, K)
{
let start = 1, end = Math.max(... arr);
let result = -1;
while (start <= end) {
let mid = Math.floor((start + end) >> 1);
let operation = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] > mid) {
operation += Math.ceil(arr[i] / mid) - 1;
}
}
if (operation <= K) {
result = mid;
end = mid - 1;
}
else {
start = mid + 1;
}
}
return result;
}
let arr = [ 2, 4, 8, 2 ];
let K = 4;
console.log(minimizeMaxElement(arr, K));
|
Time Complexity: O(log2(max(arr)) * N), where max(arr) is the maximum element and N is the size of the given array. Auxiliary Space: O(1)
Another Approach: Greedy approach with a priority queue
Another approach to solve this problem is to use a priority queue. First, we insert all the elements of the given array into the priority queue. Then, we extract the maximum element from the priority queue, break it into two halves, and insert both halves back into the priority queue. We repeat this process K times or until the maximum element in the priority queue becomes 1 or less than 1.
The idea behind this approach is that breaking a large element into two halves reduces the maximum element of the array. By repeating this process, we can gradually reduce the maximum element of the array until it becomes 1 or less than 1.
The steps of this approach are:
- Initialize a priority queue with the elements of the given array.
- Initialize a variable max_element with the maximum element of the priority queue.
- Repeat the following K times or until max_element becomes 1 or less than 1:
- Extract the maximum element from the priority queue and store it in a variable element.
- Break element into two halves and insert both halves back into the priority queue.
- Update max_element with the maximum element of the priority queue.
- If max_element becomes 1 or less than 1, break the loop.
- Return max_element.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int minimizeMaxElement(vector< int >& arr, int K)
{
priority_queue< int > pq(arr.begin(), arr.end());
int max_element = pq.top();
while (K--) {
int element = pq.top();
pq.pop();
int half = element / 2;
pq.push(half);
pq.push(element - half);
max_element = pq.top();
if (max_element <= 1) {
break ;
}
}
return max_element;
}
int main()
{
vector< int > arr = { 9 };
int K;
arr = { 2, 4, 8, 2 };
K = 4;
cout << minimizeMaxElement(arr, K) << endl;
return 0;
}
|
Python3
import heapq
def minimizeMaxElement(arr, K):
pq = [ - a for a in arr]
heapq.heapify(pq)
max_element = - pq[ 0 ]
for i in range (K):
element = - heapq.heappop(pq)
half = element / / 2
heapq.heappush(pq, - half)
heapq.heappush(pq, - (element - half))
max_element = - pq[ 0 ]
if max_element < = 1 :
break
return max_element
arr = [ 9 ]
K = 3
arr = [ 2 , 4 , 8 , 2 ]
K = 4
print (minimizeMaxElement(arr, K))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace minimizeMaxElement {
class Program {
static void Main( string [] args)
{
List< int > arr = new List< int >{ 9 };
int K;
arr = new List< int >{ 2, 4, 8, 2 };
K = 4;
Console.WriteLine(MinimizeMaxElement(arr, K));
}
static int MinimizeMaxElement(List< int > arr, int K)
{
PriorityQueue< int > pq = new PriorityQueue< int >(arr);
int max_element = pq.Peek();
while (K-- > 0) {
int element = pq.Pop();
int half = element / 2;
pq.Push(half);
pq.Push(element - half);
max_element = pq.Peek();
if (max_element <= 1)
break ;
}
return max_element;
}
}
public class PriorityQueue<T> where T : IComparable<T> {
List<T> data;
public PriorityQueue() { this .data = new List<T>(); }
public PriorityQueue(IEnumerable<T> collection)
{
this .data = new List<T>(collection);
for ( int i = (data.Count / 2) - 1; i >= 0; i--)
HeapifyDown(i);
}
public int Count() { return data.Count; }
public bool IsEmpty() { return Count() == 0; }
public T Peek()
{
if (IsEmpty())
throw new Exception( "Priority queue is empty." );
return data[0];
}
public T Pop()
{
if (IsEmpty())
throw new Exception( "Priority queue is empty." );
T element = Peek();
Swap(0, Count() - 1);
data.RemoveAt(Count() - 1);
HeapifyDown(0);
return element;
}
public void Push(T item)
{
data.Add(item);
HeapifyUp(Count() - 1);
}
private void HeapifyUp( int index)
{
if (index == 0)
return ;
int parentIndex = (index - 1) / 2;
if (data[index].CompareTo(data[parentIndex]) > 0) {
Swap(index, parentIndex);
HeapifyUp(parentIndex);
}
}
private void HeapifyDown( int index)
{
int leftIndex = (2 * index) + 1;
int rightIndex = (2 * index) + 2;
int largestIndex = index;
if (leftIndex < Count()
&& data[leftIndex].CompareTo(data[largestIndex])
> 0)
largestIndex = leftIndex;
if (rightIndex < Count()
&& data[rightIndex].CompareTo(
data[largestIndex])
> 0)
largestIndex = rightIndex;
if (largestIndex != index) {
Swap(index, largestIndex);
HeapifyDown(largestIndex);
}
}
private void Swap( int firstIndex, int secondIndex)
{
T temp = data[firstIndex];
data[firstIndex] = data[secondIndex];
data[secondIndex] = temp;
}
}
}
|
Java
import java.util.*;
class Main {
public static int minimizeMaxElement(List<Integer> arr,
int K)
{
PriorityQueue<Integer> pq = new PriorityQueue<>(
Collections.reverseOrder());
pq.addAll(arr);
int maxElement
= pq.peek();
while (
K > 0 ) {
int element
= pq.poll();
int half
= element / 2 ;
pq.offer(half);
pq.offer(element
- half);
maxElement
= pq.peek();
if (maxElement
<= 1 ) {
break ;
}
K--;
}
return maxElement;
}
public static void main(String[] args)
{
List<Integer> arr = new ArrayList<>();
int K;
arr = Arrays.asList(
2 , 4 , 8 , 2 );
K = 4 ;
System.out.println(minimizeMaxElement(
arr, K));
}
}
|
Javascript
function minimizeMaxElement(arr, K) {
let pq = new PriorityQueue();
pq.enqueue(...arr);
let max_element = pq.peek();
while (K--) {
let element = pq.dequeue();
let half = Math.floor(element / 2);
pq.enqueue(half);
pq.enqueue(element - half);
max_element = pq.peek();
if (max_element <= 1) {
break ;
}
}
return max_element;
}
class PriorityQueue {
constructor() {
this .items = [];
}
enqueue(...items) {
items.forEach((item) => {
let added = false ;
for (let i = 0; i < this .items.length; i++) {
if (item > this .items[i]) {
this .items.splice(i, 0, item);
added = true ;
break ;
}
}
if (!added) {
this .items.push(item);
}
});
}
dequeue() {
return this .items.shift();
}
peek() {
return this .items[0];
}
isEmpty() {
return this .items.length === 0;
}
size() {
return this .items.length;
}
}
let arr = [9];
let K;
arr = [2, 4, 8, 2];
K = 4;
console.log(minimizeMaxElement(arr, K));
|
Time Complexity: O(K*logN), where N is the size of the array
Auxiliary Space: O(N), where N is the size of the array
|