Open In App

Largest element after K operations on Array

Last Updated : 11 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given array A[] (1 <= A[i] <= 108) of size N (2 <= N <= 103) and integer K (1 <= K <= 108), the task is to find the largest element of the array after performing the given operation at most K times, in one operation choose i from 1 to N – 1 such that A[i] <= A[i + 1] and then increase A[i] by 1.

Examples:

Input: A[] = {1, 3, 3}, K = 4
Output: 4
Explanation:

  • Choose i = 1, Array becomes A[] = {2, 3, 3}
  • Choose i = 2, Array becomes A[] = {2, 4, 3}
  • Choose i = 1, Array becomes A[] = {3, 4, 3}
  • Choose i = 1, Array becomes A[] = {4, 4, 3}

The largest element of the above array after performing given operations optimally at most K times is 4.

Input: A[] = {1, 3, 4, 5, 1}, K = 6
Output: 7
Explanation:

  • Choose i = 3, Array becomes A[] = {1, 3, 5, 5, 1}
  • Choose i = 3, Array becomes A[] = {1, 3, 6, 5, 1}
  • Choose i = 2, Array becomes A[] = {1, 4, 6, 5, 1}
  • Choose i = 2, Array becomes A[] = {1, 5, 6, 5, 1}
  • Choose i = 2, Array becomes A[] = {1, 6, 6, 5, 1}
  • Choose i = 2, Array becomes A[] = {1, 7, 6, 5, 1}

The largest element of the above array after performing given operations optimally at most K times is 7.

Naïve Approach: The basic way to solve the problem is as follows:

Check For every value from 1 to maxArrayElement(A[]) + K is possible or not. This can be done for each value by checking if it is possible to make A[i] equal to the value that we are checking for in O(N2) for each array element.

Time Complexity: O(N3)
Auxiliary Space: O(1)

Efficient Approach: To solve the problem follow the below idea:

Binary Search can be used to solve this problem and the range of binary search will be 1 to maxArrayElement(A[]) + K. f(N) is monotonic function represents whether N can be maximum value of array after performing at most K operations. it is of the form TTTTTTFFFFFFF. we have to find when the last time function was true using Binary Search.

Below are the steps for the above approach:

  • Set low and high range of binary serach.
  • isMaximum(mid) function used to check whether mid can be largest value of array after performing given operations. For each i from 1 to N – 1 it checks the number of operations required to make it greater than equal to mid (A[i] >= mid). if number of operations are less than equal to operations available (that is K) then return true else return false.
  • Run while loop till high and low are not equal.
    • In while loop find middle element and store it in mid variable.
    • Check if that mid can be maximum value of array using isMaximum() function. If it is true then set low = mid else high = mid – 1.
  • After loop ends if isMaximum() true for high then return high else return low.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to check if given number can be
// made after performing given operations
bool isMaximum(int mid, int A[], int N, int K)
{
    // if last element of array greater than
    // equal to mid return 1
    if (A[N - 1] >= mid)
        return 1;
 
    // Define variable that tracks min number
    // of operations to make array
    // element equal to mid
    int minOperations = 1e9;
    for (int i = 0; i < N - 1; i++) {
 
        // Number of operations for each A[i]
        int noOfOperations = 0;
 
        // All elements from i should be set to
        // mid, mid - 1, mid - 2, mid - 3,
        // mid - 4, .....
        for (int j = i, offset = 0; j < N; j++, offset++) {
 
            // If A[j] is less than required
            // number that is mid - offset
            // (mid, mid - 1, mid - 2, ......)
            // we cannot change last element
            // if last element have to be set
            // to mid - offset return large
            // invalid number
            if ((mid - offset) > A[j])
                noOfOperations
                    += ((mid - offset) - A[j])
                       + ((j == N - 1) ? 2e8 : 0);
 
            // If (mid - offset) <= A[j] already
            // satisfied then break out of loop
            else
                break;
        }
 
        // Updating min number of operations
        minOperations = min(minOperations, noOfOperations);
    }
 
    // Return true if minimum number of
    // operations required to make largest
    // element of array equal to mid is less
    // than equal to operations available
    return minOperations <= K;
}
 
// Function to find Largest element after
// performing given operations at most K times
int findLargestElement(int A[], int N, int K)
{
 
    // Range of binary search
    int low = 1, high = *max_element(A, A + N) + K;
 
    // Running loop till high
    // is not equal to low
    while (high - low > 1) {
 
        // mid is average of low and high
        int mid = (low + high) / 2;
 
        // Checking test function
        if (isMaximum(mid, A, N, K)) {
            low = mid;
        }
        else {
            high = mid - 1;
        }
    }
 
    // Checking whether high can be answer
    if (isMaximum(high, A, N, K))
        return high;
 
    // If not then it is low
    else
        return low;
}
 
// Driver Code
int32_t main()
{
 
    // Input 1
    int K = 4;
    int A[] = { 1, 3, 3 }, N = 3;
 
    // Function Call
    cout << findLargestElement(A, N, K) << endl;
 
    // Input 2
    int K1 = 6;
    int A1[] = { 1, 3, 4, 5, 1 }, N1 = 5;
 
    // Function Call
    cout << findLargestElement(A1, N1, K1) << endl;
 
    return 0;
}


Java




import java.util.Arrays;
 
public class Main {
     
    // Function to check if given number can be
    // made after performing given operations
    static boolean isMaximum(int mid, int[] A, int N, int K) {
        // if last element of array greater than
        // equal to mid return true
        if (A[N - 1] >= mid)
            return true;
 
        // Define variable that tracks min number
        // of operations to make array
        // element equal to mid
        int minOperations = 1_000_000_000;
        for (int i = 0; i < N - 1; i++) {
            // Number of operations for each A[i]
            int noOfOperations = 0;
 
            // All elements from i should be set to
            // mid, mid - 1, mid - 2, mid - 3,
            // mid - 4, .....
            for (int j = i, offset = 0; j < N; j++, offset++) {
                // If A[j] is less than required
                // number that is mid - offset
                // (mid, mid - 1, mid - 2, ......)
                // we cannot change last element
                // if the last element has to be set
                // to mid - offset return a large
                // invalid number
                if ((mid - offset) > A[j])
                    noOfOperations += ((mid - offset) - A[j]) + ((j == N - 1) ? 200_000_000 : 0);
 
                // If (mid - offset) <= A[j] already
                // satisfied then break out of loop
                else
                    break;
            }
 
            // Updating min number of operations
            minOperations = Math.min(minOperations, noOfOperations);
        }
 
        // Return true if minimum number of
        // operations required to make largest
        // element of the array equal to mid is less
        // than or equal to operations available
        return minOperations <= K;
    }
 
    // Function to find Largest element after
    // performing given operations at most K times
    static int findLargestElement(int[] A, int N, int K) {
        // Range of binary search
        int low = 1, high = Arrays.stream(A).max().getAsInt() + K;
 
        // Running loop until high
        // is not equal to low
        while (high - low > 1) {
            // mid is the average of low and high
            int mid = (low + high) / 2;
 
            // Checking the test function
            if (isMaximum(mid, A, N, K)) {
                low = mid;
            } else {
                high = mid - 1;
            }
        }
 
        // Checking whether high can be the answer
        if (isMaximum(high, A, N, K))
            return high;
        // If not then it is low
        else
            return low;
    }
 
    // Driver Code
    public static void main(String[] args) {
        // Input 1
        int K = 4;
        int[] A = { 1, 3, 3 };
        int N = 3;
 
        // Function Call
        System.out.println(findLargestElement(A, N, K));
 
        // Input 2
        int K1 = 6;
        int[] A1 = { 1, 3, 4, 5, 1 };
        int N1 = 5;
 
        // Function Call
        System.out.println(findLargestElement(A1, N1, K1));
    }
}
//This code is Contributed by chinmaya121221


Python3




# Function to check if given number can be
# made after performing given operations
def is_maximum(mid, A, N, K):
    if A[N - 1] >= mid:
        return True
 
    min_operations = float('inf')
    for i in range(N - 1):
        no_of_operations = 0
 
        for j in range(i, N):
            offset = j - i
            if mid - offset > A[j]:
                no_of_operations += (mid - offset - A[j]) + (2e8 if j == N - 1 else 0)
            else:
                break
 
        min_operations = min(min_operations, no_of_operations)
 
    return min_operations <= K
 
# Function to find Largest element after
# performing given operations at most K times
def find_largest_element(A, N, K):
    low, high = 1, max(A) + K
 
    while high - low > 1:
        mid = (low + high) // 2
 
        if is_maximum(mid, A, N, K):
            low = mid
        else:
            high = mid - 1
 
    if is_maximum(high, A, N, K):
        return high
    else:
        return low
 
# Driver Code
if __name__ == "__main__":
    # Input 1
    K = 4
    A = [1, 3, 3]
    N = 3
    result = find_largest_element(A, N, K)
    print(result)
 
    # Input 2
    K1 = 6
    A1 = [1, 3, 4, 5, 1]
    N1 = 5
    result1 = find_largest_element(A1, N1, K1)
    print(result1)


C#




using System;
using System.Linq;
class Program
{
       
 
    // Function to check if given number can be
    // made after performing given operations
    static bool IsMaximum(int mid, int[] A, int N, int K)
    {
          // if last element of array greater than
        // equal to mid return 1
        if (A[N - 1] >= mid)
            return true;
       
          // Define variable that tracks min number
        // of operations to make array
        // element equal to mid
        int minOperations = int.MaxValue;
        for (int i = 0; i < N - 1; i++)
        {
              // Number of operations for each A[i]
            int noOfOperations = 0;
               
              // All elements from i should be set to
            // mid, mid - 1, mid - 2, mid - 3,
            // mid - 4, .....
            for (int j = i, offset = 0; j < N; j++, offset++)
            {
               
               // If A[j] is less than required
            // number that is mid - offset
            // (mid, mid - 1, mid - 2, ......)
            // we cannot change last element
            // if last element have to be set
            // to mid - offset return large
            // invalid number
                if ((mid - offset) > A[j])
                    noOfOperations += ((mid - offset) - A[j]) + ((j == N - 1) ? 200000000 : 0);
               
                  // If (mid - offset) <= A[j] already
                // satisfied then break out of loop
                else
                    break;
            }
           
              // Updating min number of operations
            minOperations = Math.Min(minOperations, noOfOperations);
        }
       
    // Return true if minimum number of
    // operations required to make largest
    // element of array equal to mid is less
    // than equal to operations available
        return minOperations <= K;
    }
 
      // Function to find Largest element after
    // performing given operations at most K times
    static int FindLargestElement(int[] A, int N, int K)
    {
          // Range of binary search
        int low = 1, high = A.Max() + K;
       
          // Running loop till high
        // is not equal to low
        while (high - low > 1)
        {
              // mid is average of low and high
            int mid = (low + high) / 2;
           
              // Checking test function
            if (IsMaximum(mid, A, N, K))
            {
                low = mid;
            }
            else
            {
                high = mid - 1;
            }
        }
           
          // Checking whether high can be answer
        if (IsMaximum(high, A, N, K))
            return high;
          // If not then it is low
        else
            return low;
    }
 
      // Driver Code
    static void Main(string[] args)
    {
        int K = 4;
        int[] A = { 1, 3, 3 };
        int N = 3;
        Console.WriteLine(FindLargestElement(A, N, K));
 
        int K1 = 6;
        int[] A1 = { 1, 3, 4, 5, 1 };
        int N1 = 5;
        Console.WriteLine(FindLargestElement(A1, N1, K1));
    }
}


Javascript




// Function to check if given number can be
// made after performing given operations
function isMaximum(mid, A, N, K) {
    // If the last element of the array is greater than or equal to mid, return true
    if (A[N - 1] >= mid) {
        return true;
    }
 
    // Define a variable to track the minimum number of operations to make array elements equal to mid
    let minOperations = 1e9;
    for (let i = 0; i < N - 1; i++) {
        // Number of operations for each A[i]
        let noOfOperations = 0;
 
        // All elements from i should be set to mid, mid - 1, mid - 2, mid - 3, ...
        for (let j = i, offset = 0; j < N; j++, offset++) {
            // If A[j] is less than the required number (mid - offset), we cannot change the last element
            // If the last element has to be set to mid - offset, return a large invalid number
            if (mid - offset > A[j]) {
                noOfOperations += (mid - offset - A[j]) + ((j === N - 1) ? 2e8 : 0);
            } else {
                break;
            }
        }
 
        // Update the minimum number of operations
        minOperations = Math.min(minOperations, noOfOperations);
    }
 
    // Return true if the minimum number of operations required to make the largest element of the array equal to mid is less than or equal to the available operations (K)
    return minOperations <= K;
}
 
// Function to find the largest element after
// performing given operations at most K times
function findLargestElement(A, N, K) {
    // Range of binary search
    let low = 1;
    let high = Math.max(...A) + K;
 
    // Running loop until high is not equal to low
    while (high - low > 1) {
        // Calculate mid as the average of low and high
        let mid = Math.floor((low + high) / 2);
 
        // Check with the test function
        if (isMaximum(mid, A, N, K)) {
            low = mid;
        } else {
            high = mid - 1;
        }
    }
 
    // Check if high can be the answer
    if (isMaximum(high, A, N, K)) {
        return high;
    } else {
        return low;
    }
}
 
// Driver Code
// Input 1
const K = 4;
const A = [1, 3, 3];
const N = 3;
 
// Function Call
console.log(findLargestElement(A, N, K));
 
// Input 2
const K1 = 6;
const A1 = [1, 3, 4, 5, 1];
const N1 = 5;
 
// Function Call
console.log(findLargestElement(A1, N1, K1));


Output

4
7






Time Complexity: O(N2logN)
Auxiliary Space: O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads