Open In App

Largest element after K operations on Array

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:

Below is the implementation of the above approach:




// 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;
}




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




# 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)




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));
    }
}




// 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)


Article Tags :