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:
#include <bits/stdc++.h> using namespace std;
// Define the type long long as ll for convenience typedef long long ll;
// Function to find the maximum value of the array ll findMaxValue(ll n, ll k, vector<ll>& arr) { // Variables to store the lower and upper bounds and the
// answer
ll lowerBound = 0,
upperBound
= *max_element(arr.begin(), arr.end()) + k,
answer = 0;
// Binary search for the answer
while (lowerBound <= upperBound) {
ll mid = (lowerBound + upperBound) / 2;
bool isPossible = false ;
// Try to make all elements at least mid
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 ;
}
// Update the answer and the bounds
if (isPossible) {
answer = mid;
lowerBound = mid + 1;
}
else {
upperBound = mid - 1;
}
}
return answer;
} int main()
{ // Variables to store the input numbers and the array
ll n = 3, k = 4;
vector<ll> arr = { 2, 4, 4 };
// Print the maximum value of the array
cout << findMaxValue(n, k, arr);
} |
/*code by Flutterfly */ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class Main {
// Function to find the maximum value of the array
static long findMaxValue( int n, long k, ArrayList<Long> arr) {
// Variables to store the lower and upper bounds and the answer
long lowerBound = 0 ;
long upperBound = Collections.max(arr) + k;
long answer = 0 ;
// Binary search for the answer
while (lowerBound <= upperBound) {
long mid = (lowerBound + upperBound) / 2 ;
boolean isPossible = false ;
// Try to make all elements at least mid
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 ;
}
// Update the answer and the bounds
if (isPossible) {
answer = mid;
lowerBound = mid + 1 ;
} else {
upperBound = mid - 1 ;
}
}
return answer;
}
public static void main(String[] args) {
// Variables to store the input numbers and the array
int n = 3 ;
long k = 4 ;
ArrayList<Long> arr = new ArrayList<>(Arrays.asList(2L, 4L, 4L));
// Print the maximum value of the array
System.out.println(findMaxValue(n, k, arr));
}
} |
# code by Flutterfly def find_max_value(n, k, arr):
# Variables to store the lower and upper bounds and the answer
lower_bound = 0
upper_bound = max (arr) + k
answer = 0
# Binary search for the answer
while lower_bound < = upper_bound:
mid = (lower_bound + upper_bound) / / 2
is_possible = False
# Try to make all elements at least mid
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
# Update the answer and the bounds
if is_possible:
answer = mid
lower_bound = mid + 1
else :
upper_bound = mid - 1
return answer
# Variables to store the input numbers and the array n = 3
k = 4
arr = [ 2 , 4 , 4 ]
# Print the maximum value of the array print (find_max_value(n, k, arr))
|
//code by Flutterfly using System;
using System.Linq;
class Program
{ static int FindMaxValue( int n, int k, int [] arr)
{
// Variables to store the lower and upper bounds and the answer
int lowerBound = 0;
int upperBound = arr.Max() + k;
int answer = 0;
// Binary search for the answer
while (lowerBound <= upperBound)
{
int mid = (lowerBound + upperBound) / 2;
bool isPossible = false ;
// Try to make all elements at least mid
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 ;
}
// Update the answer and the bounds
if (isPossible)
{
answer = mid;
lowerBound = mid + 1;
}
else
{
upperBound = mid - 1;
}
}
return answer;
}
static void Main()
{
// Variables to store the input numbers and the array
int n = 3;
int k = 4;
int [] arr = { 2, 4, 4 };
// Print the maximum value of the array
Console.WriteLine(FindMaxValue(n, k, arr));
}
} |
//code by flutterfly function findMaxValue(n, k, arr) {
// Variables to store the lower and upper bounds and the answer
let lowerBound = 0;
let upperBound = Math.max(...arr) + k;
let answer = 0;
// Binary search for the answer
while (lowerBound <= upperBound) {
let mid = Math.floor((lowerBound + upperBound) / 2);
let isPossible = false ;
// Try to make all elements at least mid
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 ;
}
}
// Update the answer and the bounds
if (isPossible) {
answer = mid;
lowerBound = mid + 1;
} else {
upperBound = mid - 1;
}
}
return answer;
} // Variables to store the input numbers and the array let n = 3; let k = 4; let arr = [2, 4, 4]; // Print the maximum value of the array console.log(findMaxValue(n, k, arr)); |
5
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).