Find maximum element after K increments
Last Updated :
24 Jan, 2024
Given an array arr[] of size N, in one operation you can increase arr[i] by 1 if arr[i] <= arr[i+1]. The task is to find the maximum value of the array if you can perform the above operation K number of times.
Examples:
Input: n = 3, K = 4, arr[] = {2, 4, 4}
Output: 5
Explanation: The maximum element we can have in arr[] is 5 after the following operations:
- Increment arr[1] by 1, arr[] = {2, 5, 4}
- Increment arr[2] by 1, arr[] = {2, 5, 5}
- Increment arr[1] by 1, arr[] = {2, 6, 5}
- Increment arr[2] by 1, arr[] = {2, 6, 6}
Input: n = 5, K = 6, arr[] = {1, 3, 4, 5, 1}
Output: 7
Explanation: The maximum element we can have in arr[] is 7 after the following operations:
- Increment arr[2] by 1, arr[] = {1, 3, 5, 5, 1}
- Increment arr[2] by 1, arr[] = {1, 3, 6, 5, 1}
- Increment arr[1] by 1, arr[] = {1, 4, 6, 5, 1}
- Increment arr[1] by 1, arr[] = {1, 5, 6, 5, 1}
- Increment arr[1] by 1, arr[] = {1, 6, 6, 5, 1}
- Increment arr[1] by 1, arr[] = {1, 7, 6, 5, 1}
Approach: To solve the problem, follow the below idea:
The idea is to use binary search to solve the problem. The reason binary search is suitable here is because of the property of monotonicity in the problem. If it’s possible to make all elements at least mid using K operations, then it’s also possible to make all elements at least mid – 1, mid – 2, etc., using k operations. This property allows us to use binary search to efficiently find the maximum mid for which it’s possible to make all elements at least mid.
For binary search, Initialize the lower bound to 0 and the upper bound to the maximum element in the array plus the number of operations. Performs a binary search between the lower and upper bounds. For each mid-value, check if it’s possible to make all elements at least mid using the given number of operations.
For each element in the array, calculates the minimum number of operations needed to make that element at least mid. If the total number of operations used is less than or equal to K, it’s possible to make all elements at least mid.
If it’s possible to make all elements at least mid, updates the answer to mid and moves the lower bound to mid + 1. Otherwise, it moves the upper bound to mid – 1.
Step-by-step algorithm:
- Set lowerBound to 0 and upperBound to max array element + K.
- While lowerBound <= upperBound:
- Calculate mid = (lowerBound and upperBound)/2
- For each array element:
- Check if the minimum needed value for the current element is less than or equal to the original value (arr[j]).
- If not, update the operationsUsed by the difference between the minimum needed and the original value.
- Update the minNeeded for the next element based on the current minimum needed and decrement by 1.
- Check if the total operationsUsed is within the limit of K.
- If yes, set isPossible to true.
- Check if isPossible = true, update answer = mid and lowerBound = mid + 1
- Otherwise, update upperBound = mid – 1
- Return the final answer after binary search.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll findMaxValue(ll n, ll k, vector<ll>& arr)
{
ll lowerBound = 0,
upperBound
= *max_element(arr.begin(), arr.end()) + k,
answer = 0;
while (lowerBound <= upperBound) {
ll mid = (lowerBound + upperBound) / 2;
bool isPossible = false ;
for ( int i = 0; i < n; i++) {
vector<ll> minNeeded(n);
minNeeded[i] = mid;
ll operationsUsed = 0;
for ( int j = i; j < n; j++) {
if (minNeeded[j] <= arr[j])
break ;
if (j + 1 >= n) {
operationsUsed = k + 1;
break ;
}
operationsUsed += minNeeded[j] - arr[j];
minNeeded[j + 1]
= max(0LL, minNeeded[j] - 1);
}
if (operationsUsed <= k)
isPossible = true ;
}
if (isPossible) {
answer = mid;
lowerBound = mid + 1;
}
else {
upperBound = mid - 1;
}
}
return answer;
}
int main()
{
ll n = 3, k = 4;
vector<ll> arr = { 2, 4, 4 };
cout << findMaxValue(n, k, arr);
}
|
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class Main {
static long findMaxValue( int n, long k, ArrayList<Long> arr) {
long lowerBound = 0 ;
long upperBound = Collections.max(arr) + k;
long answer = 0 ;
while (lowerBound <= upperBound) {
long mid = (lowerBound + upperBound) / 2 ;
boolean isPossible = false ;
for ( int i = 0 ; i < n; i++) {
ArrayList<Long> minNeeded = new ArrayList<>(Collections.nCopies(n, 0L));
minNeeded.set(i, mid);
long operationsUsed = 0 ;
for ( int j = i; j < n; j++) {
if (minNeeded.get(j) <= arr.get(j))
break ;
if (j + 1 >= n) {
operationsUsed = k + 1 ;
break ;
}
operationsUsed += minNeeded.get(j) - arr.get(j);
minNeeded.set(j + 1 , Math.max( 0 , minNeeded.get(j) - 1 ));
}
if (operationsUsed <= k)
isPossible = true ;
}
if (isPossible) {
answer = mid;
lowerBound = mid + 1 ;
} else {
upperBound = mid - 1 ;
}
}
return answer;
}
public static void main(String[] args) {
int n = 3 ;
long k = 4 ;
ArrayList<Long> arr = new ArrayList<>(Arrays.asList(2L, 4L, 4L));
System.out.println(findMaxValue(n, k, arr));
}
}
|
Python3
def find_max_value(n, k, arr):
lower_bound = 0
upper_bound = max (arr) + k
answer = 0
while lower_bound < = upper_bound:
mid = (lower_bound + upper_bound) / / 2
is_possible = False
for i in range (n):
min_needed = [ 0 ] * n
min_needed[i] = mid
operations_used = 0
for j in range (i, n):
if min_needed[j] < = arr[j]:
break
if j + 1 > = n:
operations_used = k + 1
break
operations_used + = min_needed[j] - arr[j]
min_needed[j + 1 ] = max ( 0 , min_needed[j] - 1 )
if operations_used < = k:
is_possible = True
if is_possible:
answer = mid
lower_bound = mid + 1
else :
upper_bound = mid - 1
return answer
n = 3
k = 4
arr = [ 2 , 4 , 4 ]
print (find_max_value(n, k, arr))
|
C#
using System;
using System.Linq;
class Program
{
static int FindMaxValue( int n, int k, int [] arr)
{
int lowerBound = 0;
int upperBound = arr.Max() + k;
int answer = 0;
while (lowerBound <= upperBound)
{
int mid = (lowerBound + upperBound) / 2;
bool isPossible = false ;
for ( int i = 0; i < n; i++)
{
int [] minNeeded = new int [n];
minNeeded[i] = mid;
int operationsUsed = 0;
for ( int j = i; j < n; j++)
{
if (minNeeded[j] <= arr[j])
break ;
if (j + 1 >= n)
{
operationsUsed = k + 1;
break ;
}
operationsUsed += minNeeded[j] - arr[j];
minNeeded[j + 1] = Math.Max(0, minNeeded[j] - 1);
}
if (operationsUsed <= k)
isPossible = true ;
}
if (isPossible)
{
answer = mid;
lowerBound = mid + 1;
}
else
{
upperBound = mid - 1;
}
}
return answer;
}
static void Main()
{
int n = 3;
int k = 4;
int [] arr = { 2, 4, 4 };
Console.WriteLine(FindMaxValue(n, k, arr));
}
}
|
Javascript
function findMaxValue(n, k, arr) {
let lowerBound = 0;
let upperBound = Math.max(...arr) + k;
let answer = 0;
while (lowerBound <= upperBound) {
let mid = Math.floor((lowerBound + upperBound) / 2);
let isPossible = false ;
for (let i = 0; i < n; i++) {
let minNeeded = Array(n).fill(0);
minNeeded[i] = mid;
let operationsUsed = 0;
for (let j = i; j < n; j++) {
if (minNeeded[j] <= arr[j]) {
break ;
}
if (j + 1 >= n) {
operationsUsed = k + 1;
break ;
}
operationsUsed += minNeeded[j] - arr[j];
minNeeded[j + 1] = Math.max(0, minNeeded[j] - 1);
}
if (operationsUsed <= k) {
isPossible = true ;
}
}
if (isPossible) {
answer = mid;
lowerBound = mid + 1;
} else {
upperBound = mid - 1;
}
}
return answer;
}
let n = 3;
let k = 4;
let arr = [2, 4, 4];
console.log(findMaxValue(n, k, arr));
|
Time complexity: O(N^2 log M), where N is the size of the array and M is the range of possible values
Auxiliary space: O(N).
Share your thoughts in the comments
Please Login to comment...