Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Length of Longest Subarray with same elements in atmost K increments

  • Difficulty Level : Hard
  • Last Updated : 10 Jun, 2021

Given an integer array arr and a number K, the task is to find the length of the longest subarray such that all the elements in this subarray can be made the same in atmost K increments.

Examples: 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: arr[] = {2, 0, 4, 6, 7}, K = 6 
Output:
The longest subarray is {2, 0, 4} which can be made as {4, 4, 4} with total increments = 6 ( ≤ K )



Input: arr[] = {12, 10, 16, 20, 7, 11}, K = 25 
Output:
The longest subarray is {12, 10, 16, 20} which can be made as {20, 20, 20, 20} with total increments = 22 ( ≤ K ) 

Approach: 
 

  • A variable i will be used to store the start point of the required longest subarray, and a variable j for the endpoint. Hence, the range will be [i, j]
  • Initially, assume the valid range to be [0, N).
  • The actual range [i, j] will be computed using binary search. For each search performed: 
    • A Segment Tree can be used to find the maximum element in the range [i, j]
    • Make all the elements in the range [i, j] equal to the found max element.
    • Then, use a prefix sum array to get the sum of elements in the range [i, j].
    • Then, the number of increments required in this range can be calculated as: 
Total number of increments
 = (j - i + 1) * (max_value) - Σ(i, j)

where i = index of the starting point of the subarray
      j = index of end point of subarray
      max_value = maximum value from index i to j
      Σ(i, j) = sum of all elements from index i to j
  • If the number of increments required is less than or equal to K, it is a valid subarray, else it is invalid.
  • For invalid subarray, update the start and end points accordingly for the next Binary Search
  • Return the length of the longest such subarray range.

Below is the implementation of the above approach:

C++




// C++ program to find the length of
// Longest Subarray with same elements
// in atmost K increments
 
#include <bits/stdc++.h>
using namespace std;
 
// Initialize array for segment tree
int segment_tree[4 * 1000000];
 
// Function that builds the segment
// tree to return the max element
// in a range
int build(int* A, int start, int end,
          int node)
{
    if (start == end)
        // update the value in segment
        // tree from given array
        segment_tree[node] = A[start];
 
    else {
        // find the middle index
        int mid = (start + end) / 2;
 
        // If there are more than one
        // elements, then recur for left
        // and right subtrees and
        // store the max of values in this node
        segment_tree[node]
            = max(
                build(A, start, mid, 2 * node + 1),
                build(A, mid + 1, end, 2 * node + 2));
    }
    return segment_tree[node];
}
 
// Function to return the max
// element in the given range
int query(int start, int end, int l, int r,
          int node)
{
    // If the range is out of bounds,
    // return -1
 
    if (start > r || end < l)
        return -1;
    if (start >= l && end <= r)
        return segment_tree[node];
    int mid = (start + end) / 2;
 
    return max(query(start, mid, l,
                     r, 2 * node + 1),
               query(mid + 1, end, l,
                     r, 2 * node + 2));
}
 
// Function that returns length of longest
// subarray with same elements in atmost
// K increments.
int longestSubArray(int* A, int N, int K)
{
 
    // Initialize the result variable
    // Even though the K is 0,
    // the required longest subarray,
    // in that case, will also be of length 1
    int res = 1;
 
    // Initialize the prefix sum array
    int preSum[N + 1];
 
    // Build the prefix sum array
    preSum[0] = A[0];
    for (int i = 0; i < N; i++)
        preSum[i + 1] = preSum[i] + A[i];
 
    // Build the segment tree
    // for range max query
    build(A, 0, N - 1, 0);
 
    // Loop through the array
    // with a starting point as i
    // for the required subarray till
    // the longest subarray is found
    for (int i = 0; i < N; i++) {
 
        int start = i, end = N - 1,
            mid, max_index = i;
 
        // Performing the binary search
        // to find the endpoint
        // for the selected range
        while (start <= end) {
 
            // Find the mid for binary search
            mid = (start + end) / 2;
 
            // Find the max element
            // in the range [i, mid]
            // using Segment Tree
            int max_element
                = query(0, N - 1,
                        i, mid, 0);
 
            // Total sum of subarray after increments
            int expected_sum = (mid - i + 1)
                               * max_element;
 
            // Actual sum of elements
            // before increments
            int actual_sum = preSum[mid + 1]
                             - preSum[i];
 
            // Check if such increment is possible
            // If true, then current i
            // is the actual starting point
            // of the required longest subarray
            if (expected_sum - actual_sum <= K) {
 
                // Now for finding the endpoint
                // for this range
                // Perform the Binary search again
                // with the updated start
                start = mid + 1;
 
                // Store max end point for the range
                // to give longest subarray
                max_index = max(max_index, mid);
            }
 
            // If false, it means that
            // the selected range is invalid
            else {
 
                // Perform the Binary Search again
                // with the updated end
                end = mid - 1;
            }
        }
 
        // Store the length of longest subarray
        res = max(res, max_index - i + 1);
    }
 
    // Return result
    return res;
}
 
// Driver code
int main()
{
    int arr[] = { 2, 0, 4, 6, 7 }, K = 6;
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << longestSubArray(arr, N, K);
 
    return 0;
}

Java




// Java program to find the length of
// Longest Subarray with same elements
// in atmost K increments
class GFG
{
     
    // Initialize array for segment tree
    static int segment_tree[] = new int[4 * 1000000];
     
    // Function that builds the segment
    // tree to return the max element
    // in a range
    static int build(int A[], int start, int end,
                     int node)
    {
        if (start == end)
         
            // update the value in segment
            // tree from given array
            segment_tree[node] = A[start];
     
        else
        {
             
            // find the middle index
            int mid = (start + end) / 2;
     
            // If there are more than one
            // elements, then recur for left
            // and right subtrees and
            // store the max of values in this node
            segment_tree[node] = Math.max(
                    build(A, start, mid, 2 * node + 1),
                    build(A, mid + 1, end, 2 * node + 2));
        }
        return segment_tree[node];
    }
     
    // Function to return the max
    // element in the given range
    static int query(int start, int end, int l, int r,
                     int node)
    {
        // If the range is out of bounds,
        // return -1
        if (start > r || end < l)
            return -1;
        if (start >= l && end <= r)
            return segment_tree[node];
        int mid = (start + end) / 2;
     
        return Math.max(query(start, mid, l,
                        r, 2 * node + 1),
                        query(mid + 1, end, l,
                        r, 2 * node + 2));
    }
     
    // Function that returns length of longest
    // subarray with same elements in atmost
    // K increments.
    static int longestSubArray(int A[], int N, int K)
    {
     
        // Initialize the result variable
        // Even though the K is 0,
        // the required longest subarray,
        // in that case, will also be of length 1
        int res = 1;
     
        // Initialize the prefix sum array
        int preSum[] = new int[N + 1];
     
        // Build the prefix sum array
        preSum[0] = A[0];
        for (int i = 0; i < N; i++)
            preSum[i + 1] = preSum[i] + A[i];
     
        // Build the segment tree
        // for range max query
        build(A, 0, N - 1, 0);
     
        // Loop through the array
        // with a starting point as i
        // for the required subarray till
        // the longest subarray is found
        for (int i = 0; i < N; i++)
        {
     
            int start = i, end = N - 1,
                mid, max_index = i;
     
            // Performing the binary search
            // to find the endpoint
            // for the selected range
            while (start <= end)
            {
     
                // Find the mid for binary search
                mid = (start + end) / 2;
     
                // Find the max element
                // in the range [i, mid]
                // using Segment Tree
                int max_element = query(0, N - 1,
                                        i, mid, 0);
     
                // Total sum of subarray after increments
                int expected_sum = (mid - i + 1)
                                * max_element;
     
                // Actual sum of elements
                // before increments
                int actual_sum = preSum[mid + 1]
                                - preSum[i];
     
                // Check if such increment is possible
                // If true, then current i
                // is the actual starting point
                // of the required longest subarray
                if (expected_sum - actual_sum <= K)
                {
     
                    // Now for finding the endpoint
                    // for this range
                    // Perform the Binary search again
                    // with the updated start
                    start = mid + 1;
     
                    // Store max end point for the range
                    // to give longest subarray
                    max_index = Math.max(max_index, mid);
                }
     
                // If false, it means that
                // the selected range is invalid
                else
                {
     
                    // Perform the Binary Search again
                    // with the updated end
                    end = mid - 1;
                }
            }
     
            // Store the length of longest subarray
            res = Math.max(res, max_index - i + 1);
        }
     
        // Return result
        return res;
    }
     
    // Driver code
    public static void main (String[] args)
    {
        int arr[] = { 2, 0, 4, 6, 7 }, K = 6;
        int N = arr.length;
     
        System.out.println(longestSubArray(arr, N, K));
    }
}
 
// This code is contributed by AnkitRai01

Python3




# Python3 program to find the length of
# Longest Subarray with same elements
# in atmost K increments
 
# Initialize array for segment tree
segment_tree = [0]*(4 * 1000000);
 
# Function that builds the segment
# tree to return the max element
# in a range
def build(A, start, end, node) :
 
    if (start == end) :
         
        # update the value in segment
        # tree from given array
        segment_tree[node] = A[start];
 
    else :
         
        # find the middle index
        mid = (start + end) // 2;
 
        # If there are more than one
        # elements, then recur for left
        # and right subtrees and
        # store the max of values in this node
        segment_tree[node] = max(
                build(A, start, mid, 2 * node + 1),
                build(A, mid + 1, end, 2 * node + 2));
 
    return segment_tree[node];
 
# Function to return the max
# element in the given range
def query(start, end, l, r, node) :
 
    # If the range is out of bounds,
    # return -1
    if (start > r or end < l) :
        return -1;
         
    if (start >= l and end <= r) :
        return segment_tree[node];
         
    mid = (start + end) // 2;
 
    return max(query(start, mid, l,
                    r, 2 * node + 1),
            query(mid + 1, end, l,
                    r, 2 * node + 2));
 
# Function that returns length of longest
# subarray with same elements in atmost
# K increments.
def longestSubArray(A, N, K) :
 
    # Initialize the result variable
    # Even though the K is 0,
    # the required longest subarray,
    # in that case, will also be of length 1
    res = 1;
 
    # Initialize the prefix sum array
    preSum = [0] * (N + 1);
 
    # Build the prefix sum array
    preSum[0] = A[0];
    for i in range(N) :
        preSum[i + 1] = preSum[i] + A[i];
 
    # Build the segment tree
    # for range max query
    build(A, 0, N - 1, 0);
 
    # Loop through the array
    # with a starting point as i
    # for the required subarray till
    # the longest subarray is found
    for i in range(N) :
 
        start = i;
        end = N - 1;
        max_index = i;
 
        # Performing the binary search
        # to find the endpoint
        # for the selected range
        while (start <= end) :
 
            # Find the mid for binary search
            mid = (start + end) // 2;
 
            # Find the max element
            # in the range [i, mid]
            # using Segment Tree
            max_element = query(0, N - 1, i, mid, 0);
 
            # Total sum of subarray after increments
            expected_sum = (mid - i + 1) * max_element;
 
            # Actual sum of elements
            # before increments
            actual_sum = preSum[mid + 1] - preSum[i];
 
            # Check if such increment is possible
            # If true, then current i
            # is the actual starting point
            # of the required longest subarray
            if (expected_sum - actual_sum <= K) :
 
                # Now for finding the endpoint
                # for this range
                # Perform the Binary search again
                # with the updated start
                start = mid + 1;
 
                # Store max end point for the range
                # to give longest subarray
                max_index = max(max_index, mid);
 
            # If false, it means that
            # the selected range is invalid
            else :
 
                # Perform the Binary Search again
                # with the updated end
                end = mid - 1;
 
        # Store the length of longest subarray
        res = max(res, max_index - i + 1);
 
    # Return result
    return res;
 
# Driver code
if __name__ == "__main__" :
 
    arr = [ 2, 0, 4, 6, 7 ]; K = 6;
    N = len(arr);
 
    print(longestSubArray(arr, N, K));
 
# This code is contributed by AnkitRai01

C#




// C# program to find the length of
// longest Subarray with same elements
// in atmost K increments
using System;
 
class GFG
{
     
    // Initialize array for segment tree
    static int []segment_tree = new int[4 * 1000000];
     
    // Function that builds the segment
    // tree to return the max element
    // in a range
    static int build(int []A, int start, int end,
                    int node)
    {
        if (start == end)
         
            // update the value in segment
            // tree from given array
            segment_tree[node] = A[start];
     
        else
        {
             
            // find the middle index
            int mid = (start + end) / 2;
     
            // If there are more than one
            // elements, then recur for left
            // and right subtrees and
            // store the max of values in this node
            segment_tree[node] = Math.Max(
                    build(A, start, mid, 2 * node + 1),
                    build(A, mid + 1, end, 2 * node + 2));
        }
        return segment_tree[node];
    }
     
    // Function to return the max
    // element in the given range
    static int query(int start, int end, int l, int r,
                    int node)
    {
        // If the range is out of bounds,
        // return -1
        if (start > r || end < l)
            return -1;
        if (start >= l && end <= r)
            return segment_tree[node];
        int mid = (start + end) / 2;
     
        return Math.Max(query(start, mid, l,
                        r, 2 * node + 1),
                        query(mid + 1, end, l,
                        r, 2 * node + 2));
    }
     
    // Function that returns length of longest
    // subarray with same elements in atmost
    // K increments.
    static int longestSubArray(int []A, int N, int K)
    {
     
        // Initialize the result variable
        // Even though the K is 0,
        // the required longest subarray,
        // in that case, will also be of length 1
        int res = 1;
     
        // Initialize the prefix sum array
        int []preSum = new int[N + 1];
     
        // Build the prefix sum array
        preSum[0] = A[0];
        for (int i = 0; i < N; i++)
            preSum[i + 1] = preSum[i] + A[i];
     
        // Build the segment tree
        // for range max query
        build(A, 0, N - 1, 0);
     
        // Loop through the array
        // with a starting point as i
        // for the required subarray till
        // the longest subarray is found
        for (int i = 0; i < N; i++)
        {
     
            int start = i, end = N - 1,
                mid, max_index = i;
     
            // Performing the binary search
            // to find the endpoint
            // for the selected range
            while (start <= end)
            {
     
                // Find the mid for binary search
                mid = (start + end) / 2;
     
                // Find the max element
                // in the range [i, mid]
                // using Segment Tree
                int max_element = query(0, N - 1,
                                        i, mid, 0);
     
                // Total sum of subarray after increments
                int expected_sum = (mid - i + 1)
                                * max_element;
     
                // Actual sum of elements
                // before increments
                int actual_sum = preSum[mid + 1]
                                - preSum[i];
     
                // Check if such increment is possible
                // If true, then current i
                // is the actual starting point
                // of the required longest subarray
                if (expected_sum - actual_sum <= K)
                {
     
                    // Now for finding the endpoint
                    // for this range
                    // Perform the Binary search again
                    // with the updated start
                    start = mid + 1;
     
                    // Store max end point for the range
                    // to give longest subarray
                    max_index = Math.Max(max_index, mid);
                }
     
                // If false, it means that
                // the selected range is invalid
                else
                {
     
                    // Perform the Binary Search again
                    // with the updated end
                    end = mid - 1;
                }
            }
     
            // Store the length of longest subarray
            res = Math.Max(res, max_index - i + 1);
        }
     
        // Return result
        return res;
    }
     
    // Driver code
    public static void Main(String[] args)
    {
        int []arr = { 2, 0, 4, 6, 7 };
        int K = 6;
        int N = arr.Length;
     
        Console.WriteLine(longestSubArray(arr, N, K));
    }
}
 
// This code is contributed by PrinciRaj1992

Javascript




<script>
    // Javascript program to find the length of
    // Longest Subarray with same elements
    // in atmost K increments
     
    // Initialize array for segment tree
    let segment_tree = new Array(4 * 1000000);
       
    // Function that builds the segment
    // tree to return the max element
    // in a range
    function build(A, start, end, node)
    {
        if (start == end)
           
            // update the value in segment
            // tree from given array
            segment_tree[node] = A[start];
       
        else
        {
               
            // find the middle index
            let mid = parseInt((start + end) / 2, 10);
       
            // If there are more than one
            // elements, then recur for left
            // and right subtrees and
            // store the max of values in this node
            segment_tree[node] = Math.max(
                    build(A, start, mid, 2 * node + 1),
                    build(A, mid + 1, end, 2 * node + 2));
        }
        return segment_tree[node];
    }
       
    // Function to return the max
    // element in the given range
    function query(start, end, l, r, node)
    {
        // If the range is out of bounds,
        // return -1
        if (start > r || end < l)
            return -1;
        if (start >= l && end <= r)
            return segment_tree[node];
        let mid = parseInt((start + end) / 2, 10);
       
        return Math.max(query(start, mid, l,
                        r, 2 * node + 1),
                        query(mid + 1, end, l,
                        r, 2 * node + 2));
    }
       
    // Function that returns length of longest
    // subarray with same elements in atmost
    // K increments.
    function longestSubArray(A, N, K)
    {
       
        // Initialize the result variable
        // Even though the K is 0,
        // the required longest subarray,
        // in that case, will also be of length 1
        let res = 1;
       
        // Initialize the prefix sum array
        let preSum = new Array(N + 1);
       
        // Build the prefix sum array
        preSum[0] = A[0];
        for (let i = 0; i < N; i++)
            preSum[i + 1] = preSum[i] + A[i];
       
        // Build the segment tree
        // for range max query
        build(A, 0, N - 1, 0);
       
        // Loop through the array
        // with a starting point as i
        // for the required subarray till
        // the longest subarray is found
        for (let i = 0; i < N; i++)
        {
       
            let start = i, end = N - 1, mid, max_index = i;
       
            // Performing the binary search
            // to find the endpoint
            // for the selected range
            while (start <= end)
            {
       
                // Find the mid for binary search
                mid = parseInt((start + end) / 2, 10);
       
                // Find the max element
                // in the range [i, mid]
                // using Segment Tree
                let max_element = query(0, N - 1, i, mid, 0);
       
                // Total sum of subarray after increments
                let expected_sum = (mid - i + 1) * max_element;
       
                // Actual sum of elements
                // before increments
                let actual_sum = preSum[mid + 1] - preSum[i];
       
                // Check if such increment is possible
                // If true, then current i
                // is the actual starting point
                // of the required longest subarray
                if (expected_sum - actual_sum <= K)
                {
       
                    // Now for finding the endpoint
                    // for this range
                    // Perform the Binary search again
                    // with the updated start
                    start = mid + 1;
       
                    // Store max end point for the range
                    // to give longest subarray
                    max_index = Math.max(max_index, mid);
                }
       
                // If false, it means that
                // the selected range is invalid
                else
                {
       
                    // Perform the Binary Search again
                    // with the updated end
                    end = mid - 1;
                }
            }
       
            // Store the length of longest subarray
            res = Math.max(res, max_index - i + 1);
        }
       
        // Return result
        return res;
    }
     
    let arr = [ 2, 0, 4, 6, 7 ], K = 6;
    let N = arr.length;
 
    document.write(longestSubArray(arr, N, K));
     
</script>
Output: 
3

 

Time Complexity: O(N*(log(N))2)
 




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!