Length of Longest Subarray with same elements in atmost K increments - GeeksforGeeks

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: 
Input: arr[] = {2, 0, 4, 6, 7}, K = 6 Output: 3 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: 4 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: 
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++
Java
Python3
C#
Javascript
// 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 treeint segment_tree[4 * 1000000]; // Function that builds the segment// tree to return the max element// in a rangeint 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 rangeint 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 codeint 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 program to find the length of// Longest Subarray with same elements// in atmost K incrementsclass 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 program to find the length of# Longest Subarray with same elements# in atmost K increments # Initialize array for segment treesegment_tree = [0]*(4 * 1000000); # Function that builds the segment# tree to return the max element# in a rangedef 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 rangedef 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 codeif __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# program to find the length of// longest Subarray with same elements// in atmost K incrementsusing 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
<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>
3
 
Time Complexity: O(N*(log(N))2) 
ankthon
princiraj1992
decode2207
Binary Search
prefix-sum
Segment-Tree
subarray
Arrays
Searching
Tree
prefix-sum
Arrays
Searching
Tree
Segment-Tree
Binary Search
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Introduction to Arrays
Maximum and minimum of an array using minimum number of comparisons
Multidimensional Arrays in Java
Queue | Set 1 (Introduction and Array Implementation)
Linked List vs Array
Binary Search
Maximum and minimum of an array using minimum number of comparisons
Find the Missing Number
K'th Smallest/Largest Element in Unsorted Array | Set 1
Program to find largest element in an array