Open in App
Not now

# Maximize length of longest subarray consisting of same elements by at most K decrements

• Last Updated : 11 Jul, 2022

Given an array arr[] of size N and an integer K, the task is to find the length of the longest subarray consisting of same elements that can be obtained by decrementing the array elements by 1 at most K times.

Example:

Input: arr[] = { 1, 2, 3 }, K = 1
Output: 2
Explanation:
Decrementing arr[0] by 1 modifies arr[] to { 1, 1, 3 }
The longest subarray with equal elements is { 1, 1 }.
Therefore, the required output is 2.

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

Approach: The problem can be solved using Segment tree and Binary Search technique. The idea is to use the following observations:

Total number of decrements operations required to make all array elements of the subarray { arr[start], …, arr[end] } equal
= (Î£(start, end)) – (end – start + 1) * (min_value)

where, start = index of the starting point of the subarray
end = index of end point of subarray
min_value = smallest value from index i to j
Î£(start, end) = sum of all elements from index i to j

Follow the steps below to solve the above problem:

1. Initialize a segment tree to calculate the smallest element in a subarray of the array and a prefix sum array to calculate the sum elements of a subarray.
2. Traverse the array, arr[]. For every ith element perform the following operations:
• Initialize two variables say, start = i, end = N – 1 and apply binary search over the range [start, end] to check if the all the elements of the subarray { arr[start], …, arr[end] } can be made equal or not by decrementing at most K operations from the above observations.
• If all the elements of the subarray { arr[start], …, arr[end] } can be made equal by decrementing at most K operations then update start = (start + end) / 2 + 1.
• Otherwise, update end = (start + end) / 2 – 1

3. Finally, print the length of the longest subarray obtained from the above operations.

Below is the implementation of the above approach:

## C++

 `// C++ program to implement ` `// the above approach ` ` `  `#include ` `using` `namespace` `std; ` ` `  `// Function to construct Segment Tree ` `// to return the minimum element in a range ` `int` `build(``int` `tree[], ``int``* A, ``int` `start, ` `          ``int` `end, ``int` `node) ` `{ ` `    ``// If leaf nodes of ` `    ``// the tree are found ` `    ``if` `(start == end) { ` ` `  `        ``// Update the value in segment ` `        ``// tree from given array ` `        ``tree[node] = A[start]; ` ` `  `        ``return` `tree[node]; ` `    ``} ` ` `  `    ``// Divide left and right subtree ` `    ``int` `mid = (start + end) / 2; ` ` `  `    ``// Stores smallest element in ` `    ``// subarray { arr[start], arr[mid] } ` `    ``int` `X = build(tree, A, start, mid, ` `                  ``2 * node + 1); ` ` `  `    ``// Stores smallest element in ` `    ``// subarray { arr[mid + 1], arr[end] } ` `    ``int` `Y = build(tree, A, mid + 1, ` `                  ``end, 2 * node + 2); ` ` `  `    ``// Stores smallest element in ` `    ``// subarray { arr[start], arr[end] } ` `    ``return` `tree[node] = min(X, Y); ` `} ` ` `  `// Function to find the smallest ` `// element present in a subarray ` `int` `query(``int` `tree[], ``int` `start, ``int` `end, ` `          ``int` `l, ``int` `r, ``int` `node) ` `{ ` `    ``// If elements of the subarray ` `    ``// are not in the range [l, r] ` `    ``if` `(start > r || end < l) ` `        ``return` `INT_MAX; ` ` `  `    ``// If all the elements of the ` `    ``// subarray are in the range [l, r] ` `    ``if` `(start >= l && end <= r) ` `        ``return` `tree[node]; ` ` `  `    ``// Divide tree into left ` `    ``// and right subtree ` `    ``int` `mid = (start + end) / 2; ` ` `  `    ``// Stores smallest element ` `    ``// in left subtree ` `    ``int` `X = query(tree, start, mid, l, ` `                  ``r, 2 * node + 1); ` ` `  `    ``// Stores smallest element in ` `    ``// right subtree ` `    ``int` `Y = query(tree, mid + 1, end, l, ` `                  ``r, 2 * node + 2); ` ` `  `    ``return` `min(X, Y); ` `} ` ` `  `// Function that find length of longest ` `// subarray with all equal elements in ` `// atmost K decrements ` `int` `longestSubArray(``int``* A, ``int` `N, ``int` `K) ` `{ ` `    ``// Stores length of longest subarray ` `    ``// with all equal elements in atmost ` `    ``// K decrements. ` `    ``int` `res = 1; ` ` `  `    ``// Store the prefix sum array ` `    ``int` `preSum[N + 1]; ` ` `  `    ``// Calculate the prefix sum array ` `    ``preSum[0] = A[0]; ` `    ``for` `(``int` `i = 0; i < N; i++) ` `        ``preSum[i + 1] = preSum[i] + A[i]; ` ` `  `    ``int` `tree[4 * N + 5]; ` ` `  `    ``// Build the segment tree ` `    ``// for range min query ` `    ``build(tree, A, 0, N - 1, 0); ` ` `  `    ``// Traverse the array ` `    ``for` `(``int` `i = 0; i < N; i++) { ` ` `  `        ``// Stores start index ` `        ``// of the subarray ` `        ``int` `start = i; ` ` `  `        ``// Stores end index ` `        ``// of the subarray ` `        ``int` `end = N - 1; ` ` `  `        ``int` `mid; ` ` `  `        ``// Stores end index of ` `        ``// the longest subarray ` `        ``int` `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 smallest element in ` `            ``// range [i, mid] using Segment Tree ` `            ``int` `min_element ` `                ``= query(tree, 0, N - 1, i, mid, 0); ` ` `  `            ``// Stores total sum of subarray ` `            ``// after K decrements ` `            ``int` `expected_sum ` `                ``= (mid - i + 1) * min_element; ` ` `  `            ``// Stores sum of elements of ` `            ``// subarray before K decrements ` `            ``int` `actual_sum ` `                ``= preSum[mid + 1] - preSum[i]; ` ` `  `            ``// If subarray found with ` `            ``// all equal elements ` `            ``if` `(actual_sum - expected_sum <= K) { ` ` `  `                ``// Update start ` `                ``start = mid + 1; ` ` `  `                ``// Update max_index ` `                ``max_index = max(max_index, mid); ` `            ``} ` ` `  `            ``// If false, it means that ` `            ``// the selected range is invalid ` `            ``else` `{ ` ` `  `                ``// Update 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[] = { 1, 7, 3, 4, 5, 6 }; ` `    ``int` `k = 6; ` `    ``int` `n = 6; ` `    ``cout << longestSubArray(arr, n, k); ` ` `  `    ``return` `0; ` `} `

## Java

 `// Java program to implement  ` `// the above approach  ` `import` `java.util.*; ` `  `  `class` `GFG{ ` ` `  `// Function to construct Segment Tree ` `// to return the minimum element in a range ` `static` `int` `build(``int` `tree[], ``int``[] A, ``int` `start, ` `                 ``int` `end, ``int` `node) ` `{ ` `     `  `    ``// If leaf nodes of ` `    ``// the tree are found ` `    ``if` `(start == end)  ` `    ``{ ` `         `  `        ``// Update the value in segment ` `        ``// tree from given array ` `        ``tree[node] = A[start]; ` `  `  `        ``return` `tree[node]; ` `    ``} ` `  `  `    ``// Divide left and right subtree ` `    ``int` `mid = (start + end) / ``2``; ` `  `  `    ``// Stores smallest element in ` `    ``// subarray { arr[start], arr[mid] } ` `    ``int` `X = build(tree, A, start, mid, ` `                  ``2` `* node + ``1``); ` `  `  `    ``// Stores smallest element in ` `    ``// subarray { arr[mid + 1], arr[end] } ` `    ``int` `Y = build(tree, A, mid + ``1``, ` `                 ``end, ``2` `* node + ``2``); ` `  `  `    ``// Stores smallest element in ` `    ``// subarray { arr[start], arr[end] } ` `    ``return` `(tree[node] = Math.min(X, Y)); ` `} ` `  `  `// Function to find the smallest ` `// element present in a subarray ` `static` `int` `query(``int` `tree[], ``int` `start, ``int` `end, ` `                 ``int` `l, ``int` `r, ``int` `node) ` `{ ` `     `  `    ``// If elements of the subarray ` `    ``// are not in the range [l, r] ` `    ``if` `(start > r || end < l) ` `        ``return` `Integer.MAX_VALUE; ` `  `  `    ``// If all the elements of the ` `    ``// subarray are in the range [l, r] ` `    ``if` `(start >= l && end <= r) ` `        ``return` `tree[node]; ` `  `  `    ``// Divide tree into left ` `    ``// and right subtree ` `    ``int` `mid = (start + end) / ``2``; ` `  `  `    ``// Stores smallest element ` `    ``// in left subtree ` `    ``int` `X = query(tree, start, mid, l, ` `                  ``r, ``2` `* node + ``1``); ` `  `  `    ``// Stores smallest element in ` `    ``// right subtree ` `    ``int` `Y = query(tree, mid + ``1``, end, l, ` `                  ``r, ``2` `* node + ``2``); ` `  `  `    ``return` `Math.min(X, Y); ` `} ` `  `  `// Function that find length of longest ` `// subarray with all equal elements in ` `// atmost K decrements ` `static` `int` `longestSubArray(``int``[] A, ``int` `N, ``int` `K) ` `{ ` `     `  `    ``// Stores length of longest subarray ` `    ``// with all equal elements in atmost ` `    ``// K decrements. ` `    ``int` `res = ``1``; ` `  `  `    ``// Store the prefix sum array ` `    ``int` `preSum[] = ``new` `int``[N + ``1``]; ` `  `  `    ``// Calculate the prefix sum array ` `    ``preSum[``0``] = A[``0``]; ` `    ``for``(``int` `i = ``0``; i < N; i++) ` `        ``preSum[i + ``1``] = preSum[i] + A[i]; ` `  `  `    ``int` `tree[] = ``new` `int``[``4` `* N + ``5``]; ` `  `  `    ``// Build the segment tree ` `    ``// for range min query ` `    ``build(tree, A, ``0``, N - ``1``, ``0``); ` `  `  `    ``// Traverse the array ` `    ``for``(``int` `i = ``0``; i < N; i++)  ` `    ``{ ` `         `  `        ``// Stores start index ` `        ``// of the subarray ` `        ``int` `start = i; ` `  `  `        ``// Stores end index ` `        ``// of the subarray ` `        ``int` `end = N - ``1``; ` `  `  `        ``int` `mid; ` `  `  `        ``// Stores end index of ` `        ``// the longest subarray ` `        ``int` `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 smallest element in ` `            ``// range [i, mid] using Segment Tree ` `            ``int` `min_element = query(tree, ``0``, N - ``1``, ` `                                    ``i, mid, ``0``); ` `  `  `            ``// Stores total sum of subarray ` `            ``// after K decrements ` `            ``int` `expected_sum = (mid - i + ``1``) * ` `                                ``min_element; ` `  `  `            ``// Stores sum of elements of ` `            ``// subarray before K decrements ` `            ``int` `actual_sum = preSum[mid + ``1``] -  ` `                             ``preSum[i]; ` `  `  `            ``// If subarray found with ` `            ``// all equal elements ` `            ``if` `(actual_sum - expected_sum <= K)  ` `            ``{ ` `                 `  `                ``// Update start ` `                ``start = mid + ``1``; ` `  `  `                ``// Update max_index ` `                ``max_index = Math.max(max_index, mid); ` `            ``} ` `  `  `            ``// If false, it means that ` `            ``// the selected range is invalid ` `            ``else`  `            ``{ ` `                 `  `                ``// Update end ` `                ``end = mid - ``1``; ` `            ``} ` `        ``} ` `  `  `        ``// Store the length of longest subarray ` `        ``res = Math.max(res, max_index - i + ``1``); ` `    ``} ` `  `  `    ``// Return result ` `    ``return` `res; ` `} ` `  `  `// Driver Code ` `static` `public` `void` `main(String args[]) ` `{ ` `    ``int` `arr[] = { ``1``, ``7``, ``3``, ``4``, ``5``, ``6` `}; ` `    ``int` `k = ``6``; ` `    ``int` `n = ``6``; ` `     `  `    ``System.out.print(longestSubArray(arr, n, k)); ` `} ` `} ` ` `  `// This code is contributed by sanjoy_62`

## Python3

 `# Python3 program to implement ` `# the above approach ` `import` `sys ` ` `  `# Function to construct Segment Tree ` `# to return the minimum element in a range ` `def` `build(tree, A, start, end, node): ` `     `  `    ``# If leaf nodes of ` `    ``# the tree are found ` `    ``if` `(start ``=``=` `end): ` `         `  `        ``# Update the value in segment ` `        ``# tree from given array ` `        ``tree[node] ``=` `A[start] ` `  `  `        ``return` `tree[node] ` `     `  `    ``# Divide left and right subtree ` `    ``mid ``=` `(``int``)((start ``+` `end) ``/` `2``) ` `  `  `    ``# Stores smallest element in ` `    ``# subarray : arr[start], arr[mid]  ` `    ``X ``=` `build(tree, A, start, mid, ` `              ``2` `*` `node ``+` `1``) ` ` `  `    ``# Stores smallest element in ` `    ``# subarray : arr[mid + 1], arr[end]  ` `    ``Y ``=` `build(tree, A, mid ``+` `1``, ` `             ``end, ``2` `*` `node ``+` `2``) ` `  `  `    ``# Stores smallest element in ` `    ``# subarray : arr[start], arr[end]  ` `    ``return` `(tree[node] ``=``=` `min``(X, Y)) ` ` `  `# Function to find the smallest ` `# element present in a subarray ` `def` `query(tree, start, end, l, r, node): ` `               `  `    ``# If elements of the subarray ` `    ``# are not in the range [l, r] ` `    ``if` `(start > r ``or` `end < l) : ` `        ``return` `sys.maxsize ` `  `  `    ``# If all the elements of the ` `    ``# subarray are in the range [l, r] ` `    ``if` `(start >``=` `l ``and` `end <``=` `r): ` `        ``return` `tree[node] ` `  `  `    ``# Divide tree into left ` `    ``# and right subtree ` `    ``mid ``=` `(``int``)((start ``+` `end) ``/` `2``) ` `  `  `    ``# Stores smallest element ` `    ``# in left subtree ` `    ``X ``=` `query(tree, start, mid, l, ` `              ``r, ``2` `*` `node ``+` `1``) ` `  `  `    ``# Stores smallest element in ` `    ``# right subtree ` `    ``Y ``=` `query(tree, mid ``+` `1``, end, l, ` `            ``r, ``2` `*` `node ``+` `2``) ` `  `  `    ``return` `min``(X, Y) ` ` `  `# Function that find length of longest ` `# subarray with all equal elements in ` `# atmost K decrements ` `def` `longestSubArray(A, N, K): ` `     `  `    ``# Stores length of longest subarray ` `    ``# with all equal elements in atmost ` `    ``# K decrements. ` `    ``res ``=` `1` `  `  `    ``# Store the prefix sum array ` `    ``preSum ``=` `[``0``] ``*` `(N ``+` `1``) ` `  `  `    ``# Calculate the prefix sum array ` `    ``preSum[``0``] ``=` `A[``0``] ` `    ``for` `i ``in` `range``(N): ` `        ``preSum[i ``+` `1``] ``=` `preSum[i] ``+` `A[i] ` `  `  `    ``tree ``=` `[``0``] ``*` `(``4` `*` `N ``+` `5``) ` `  `  `    ``# Build the segment tree ` `    ``# for range min query ` `    ``build(tree, A, ``0``, N ``-` `1``, ``0``) ` `  `  `    ``# Traverse the array ` `    ``for` `i ``in` `range``(N): ` `  `  `        ``# Stores start index ` `        ``# of the subarray ` `        ``start ``=` `i ` `  `  `        ``# Stores end index ` `        ``# of the subarray ` `        ``end ``=` `N ``-` `1` `  `  `        ``# Stores end index of ` `        ``# the longest subarray ` `        ``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 ``=` `(``int``)((start ``+` `end) ``/` `2``) ` `  `  `            ``# Find the smallest element in ` `            ``# range [i, mid] using Segment Tree ` `            ``min_element ``=` `query(tree, ``0``, N ``-` `1``, i, mid, ``0``) ` `  `  `            ``# Stores total sum of subarray ` `            ``# after K decrements ` `            ``expected_sum ``=` `(mid ``-` `i ``+` `1``) ``*` `min_element ` `  `  `            ``# Stores sum of elements of ` `            ``# subarray before K decrements ` `            ``actual_sum ``=` `preSum[mid ``+` `1``] ``-` `preSum[i] ` `  `  `            ``# If subarray found with ` `            ``# all equal elements ` `            ``if` `(actual_sum ``-` `expected_sum <``=` `K): ` `                 `  `                ``# Update start ` `                ``start ``=` `mid ``+` `1` `  `  `                ``# Update max_index ` `                ``max_index ``=` `max``(max_index, mid) ` `             `  `            ``# If false, it means that ` `            ``# the selected range is invalid ` `            ``else``: ` `  `  `                ``# Update end ` `                ``end ``=` `mid ``-` `1` `             `  `        ``# Store the length of longest subarray ` `        ``res ``=` `max``(res, max_index ``-` `i ``+` `2``) ` ` `  `    ``# Return result ` `    ``return` `res ` ` `  `# Driver Code ` `arr ``=` `[ ``1``, ``7``, ``3``, ``4``, ``5``, ``6` `] ` `k ``=` `6` `n ``=` `6` ` `  `print``(longestSubArray(arr, n, k)) ` ` `  `# This code is contributed by splevel62`

## C#

 `// C# program to implement  ` `// the above approach  ` `using` `System; ` `  `  `class` `GFG{ ` `      `  `// Function to construct Segment Tree ` `// to return the minimum element in a range ` `static` `int` `build(``int``[] tree, ``int``[] A, ``int` `start, ` `                 ``int` `end, ``int` `node) ` `{ ` `     `  `    ``// If leaf nodes of ` `    ``// the tree are found ` `    ``if` `(start == end)  ` `    ``{ ` `         `  `        ``// Update the value in segment ` `        ``// tree from given array ` `        ``tree[node] = A[start]; ` `   `  `        ``return` `tree[node]; ` `    ``} ` `   `  `    ``// Divide left and right subtree ` `    ``int` `mid = (start + end) / 2; ` `   `  `    ``// Stores smallest element in ` `    ``// subarray { arr[start], arr[mid] } ` `    ``int` `X = build(tree, A, start, mid, ` `                  ``2 * node + 1); ` `   `  `    ``// Stores smallest element in ` `    ``// subarray { arr[mid + 1], arr[end] } ` `    ``int` `Y = build(tree, A, mid + 1, ` `                  ``end, 2 * node + 2); ` `   `  `    ``// Stores smallest element in ` `    ``// subarray { arr[start], arr[end] } ` `    ``return` `(tree[node] = Math.Min(X, Y)); ` `} ` `   `  `// Function to find the smallest ` `// element present in a subarray ` `static` `int` `query(``int``[] tree, ``int` `start, ``int` `end, ` `                 ``int` `l, ``int` `r, ``int` `node) ` `{ ` `      `  `    ``// If elements of the subarray ` `    ``// are not in the range [l, r] ` `    ``if` `(start > r || end < l) ` `        ``return` `Int32.MaxValue; ` `   `  `    ``// If all the elements of the ` `    ``// subarray are in the range [l, r] ` `    ``if` `(start >= l && end <= r) ` `        ``return` `tree[node]; ` `   `  `    ``// Divide tree into left ` `    ``// and right subtree ` `    ``int` `mid = (start + end) / 2; ` `   `  `    ``// Stores smallest element ` `    ``// in left subtree ` `    ``int` `X = query(tree, start, mid, l, ` `                  ``r, 2 * node + 1); ` `   `  `    ``// Stores smallest element in ` `    ``// right subtree ` `    ``int` `Y = query(tree, mid + 1, end, l, ` `                  ``r, 2 * node + 2); ` `   `  `    ``return` `Math.Min(X, Y); ` `} ` `   `  `// Function that find length of longest ` `// subarray with all equal elements in ` `// atmost K decrements ` `static` `int` `longestSubArray(``int``[] A, ``int` `N, ``int` `K) ` `{ ` `      `  `    ``// Stores length of longest subarray ` `    ``// with all equal elements in atmost ` `    ``// K decrements. ` `    ``int` `res = 1; ` `   `  `    ``// Store the prefix sum array ` `    ``int``[] preSum = ``new` `int``[N + 1]; ` `   `  `    ``// Calculate the prefix sum array ` `    ``preSum[0] = A[0]; ` `    ``for``(``int` `i = 0; i < N; i++) ` `        ``preSum[i + 1] = preSum[i] + A[i]; ` `   `  `    ``int``[] tree = ``new` `int``[4 * N + 5]; ` `   `  `    ``// Build the segment tree ` `    ``// for range min query ` `    ``build(tree, A, 0, N - 1, 0); ` `   `  `    ``// Traverse the array ` `    ``for``(``int` `i = 0; i < N; i++)  ` `    ``{ ` `          `  `        ``// Stores start index ` `        ``// of the subarray ` `        ``int` `start = i; ` `   `  `        ``// Stores end index ` `        ``// of the subarray ` `        ``int` `end = N - 1; ` `   `  `        ``int` `mid; ` `   `  `        ``// Stores end index of ` `        ``// the longest subarray ` `        ``int` `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 smallest element in ` `            ``// range [i, mid] using Segment Tree ` `            ``int` `min_element = query(tree, 0, N - 1, ` `                                    ``i, mid, 0); ` `   `  `            ``// Stores total sum of subarray ` `            ``// after K decrements ` `            ``int` `expected_sum = (mid - i + 1) * ` `                                ``min_element; ` `   `  `            ``// Stores sum of elements of ` `            ``// subarray before K decrements ` `            ``int` `actual_sum = preSum[mid + 1] -  ` `                             ``preSum[i]; ` `   `  `            ``// If subarray found with ` `            ``// all equal elements ` `            ``if` `(actual_sum - expected_sum <= K)  ` `            ``{ ` `                  `  `                ``// Update start ` `                ``start = mid + 1; ` `   `  `                ``// Update max_index ` `                ``max_index = Math.Max(max_index, mid); ` `            ``} ` `   `  `            ``// If false, it means that ` `            ``// the selected range is invalid ` `            ``else` `            ``{ ` `                  `  `                ``// Update end ` `                ``end = mid - 1; ` `            ``} ` `        ``} ` `   `  `        ``// Store the length of longest subarray ` `        ``res = Math.Max(res, max_index - i + 1); ` `    ``} ` `   `  `    ``// Return result ` `    ``return` `res; ` `} ` `  `  `// Driver Code ` `static` `void` `Main() ` `{ ` `    ``int``[] arr = { 1, 7, 3, 4, 5, 6 }; ` `    ``int` `k = 6; ` `    ``int` `n = 6; ` `      `  `    ``Console.WriteLine(longestSubArray(arr, n, k)); ` `} ` `} ` ` `  `// This code is contributed by susmitakundugoaldanga`

## Javascript

 ``

Output:

`4`

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

Related Topic: Segment Tree

My Personal Notes arrow_drop_up
Related Articles