Longest subarray with given conditions
Last Updated :
11 Jan, 2024
Given 2 integers S and K and an array arr[] of N integers, find the longest subarray in arr[] such that the subarray can be divided into at most K contiguous segments and the sum of elements of each segment can be at most S.
Example:
Input: n = 5, k = 2, s = 5, arr = { 1, 3, 2, 1, 5 }
Output: 4
Explanation: One of the segments with length 4 is [1,3,2,1]. It can be divided into two segments [1,3] and [2,1] whose sums are at most S=5.
Input: n = 5, k = 3, s = 5, arr = {5, 1 ,5 ,1 ,1}
Output: 4
Explanation: One of the segments with length 4 is [1,5,1,1]. It can be divided into three segments [1], [5] and [1,1] whose sums are at most S=5.
Approach:
The idea is to uses a two-pointer approach to find the right boundary of each segment, precomputes right boundaries using binary lifting, and make use of binary lifting to determine the maximum number of elements in a good segment for each starting index. The result is the maximum value encountered during these calculations.
- Initialize Variables:
- Set up variables for the current sum (currSum) and the maximum number of elements in a good segment (maxGoodSegment).
- Segment Boundary Calculation:
- Use a two-pointer approach to find the right boundary of each segment:
- Iterate over possible left boundaries.
- Extend the right boundary until the sum exceeds s.
- Store the right boundary in the 2D array up.
- Precompute Right Boundaries:
- Use binary lifting to precompute the right boundaries for each power of 2.
- Binary Lifting for Maximum Segments:
- Use binary lifting to find the maximum number of elements in a good segment for each starting index (i):
- Iterate over the binary representation of k.
- Update the current index based on the binary lifting technique.
- Track the maximum segment size encountered during these iterations.
- Output Result:
- The maximum number of elements in a good segment (maxGoodSegment) represents the solution for the given input
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5;
int up[MAX_N + 5][20];
int solve(int n, int k, int s, vector<int>& arr)
{
vector<int> nums(n, 0);
int currSum = 0;
int maxGoodSegment = 0;
// Calculate the maximum number of elements in a good
// segment
for (int i = 0, j = 0; i < n; i++) {
// Extend the current segment until the sum exceeds
// 's'
while (j < n && currSum + arr[j] <= s) {
currSum += arr[j];
j++;
}
// Store the right boundary of the current segment
up[i][0] = j;
currSum -= arr[i]; // Move the left boundary of the
// segment
}
up[n][0] = n;
// Precompute the right boundaries for each power of 2
for (int j = 1; j < 20; j++) {
for (int i = 0; i <= n; i += 1) {
up[i][j] = up[up[i][j - 1]][j - 1];
}
}
// Calculate the maximum number of elements in a good
// segment using binary lifting
for (int i = 0; i < n; i++) {
int currIndex = i;
for (int j = 19; j >= 0; j--) {
if (k & (1 << j)) {
currIndex = up[currIndex][j];
}
}
maxGoodSegment = max(maxGoodSegment, currIndex - i);
}
// Output the result for the current test case
return maxGoodSegment;
}
int main()
{
int n = 5, k = 2, s = 5;
vector<int> arr = { 1, 3, 2, 1, 5 };
cout << solve(n, k, s, arr);
return 0;
}
Java
import java.util.Arrays;
import java.util.Vector;
public class Main {
static final int MAX_N = 100005;
static int[][] up = new int[MAX_N + 5][20];
static int solve(int n, int k, int s, Vector<Integer> arr) {
// Vector to store nums array, initialized with 0
Vector<Integer> nums = new Vector<>(n);
for (int i = 0; i < n; i++) {
nums.add(0);
}
int currSum = 0;
int maxGoodSegment = 0;
// Calculate the right boundaries of segments
for (int i = 0, j = 0; i < n; i++) {
while (j < n && currSum + arr.get(j) <= s) {
currSum += arr.get(j);
j++;
}
up[i][0] = j; // Store the right boundary of the current segment
currSum -= arr.get(i); // Move the left boundary of the segment
}
up[n][0] = n; // Set the right boundary of the last element
// Precompute the right boundaries for each power of 2 using binary lifting
for (int j = 1; j < 20; j++) {
for (int i = 0; i <= n; i += 1) {
up[i][j] = up[up[i][j - 1]][j - 1];
}
}
// Calculate the maximum number of elements in a good segment using binary lifting
for (int i = 0; i < n; i++) {
int currIndex = i;
for (int j = 19; j >= 0; j--) {
if ((k & (1 << j)) != 0) {
currIndex = up[currIndex][j];
}
}
maxGoodSegment = Math.max(maxGoodSegment, currIndex - i);
}
return maxGoodSegment;
}
public static void main(String[] args) {
// Example input
int n = 5, k = 2, s = 5;
Vector<Integer> arr = new Vector<>(Arrays.asList(1, 3, 2, 1, 5));
// Output the result for the current test case
System.out.println(solve(n, k, s, arr));
}
}
// This code is contributed by akshitaguprzj3
Python3
MAX_N = 10**5
up = [[0] * 20 for _ in range(MAX_N + 5)]
def solve(n, k, s, arr):
nums = [0] * n
curr_sum = 0
max_good_segment = 0
# Calculate the maximum number of elements in a good segment
for i in range(n):
j = i
# Extend the current segment until the sum exceeds 's'
while j < n and curr_sum + arr[j] <= s:
curr_sum += arr[j]
j += 1
# Store the right boundary of the current segment
up[i][0] = j
curr_sum -= arr[i] # Move the left boundary of the segment
up[n][0] = n
# Precompute the right boundaries for each power of 2
for j in range(1, 20):
for i in range(n + 1):
up[i][j] = up[up[i][j - 1]][j - 1]
# Calculate the maximum number of elements in a good segment using binary lifting
for i in range(n):
curr_index = i
for j in range(19, -1, -1):
if k & (1 << j):
curr_index = up[curr_index][j]
max_good_segment = max(max_good_segment, curr_index - i)
# Output the result for the current test case
return max_good_segment
if __name__ == "__main__":
n, k, s = 5, 2, 5
arr = [1, 3, 2, 1, 5]
print(solve(n, k, s, arr))
C#
using System;
using System.Collections.Generic;
public class Solution
{
const int MAX_N = 100005;
static int[,] up = new int[MAX_N + 5, 20];
static int Solve(int n, int k, int s, List<int> arr)
{
int currSum = 0;
int maxGoodSegment = 0;
// Calculate the maximum number of elements in a good
// segment
for (int i = 0, j = 0; i < n; i++)
{
// Extend the current segment until the sum exceeds
// 's'
while (j < n && currSum + arr[j] <= s)
{
currSum += arr[j];
j++;
}
// Store the right boundary of the current segment
up[i, 0] = j;
currSum -= arr[i]; // Move the left boundary of the
// segment
}
up[n, 0] = n;
// Precompute the right boundaries for each power of 2
for (int j = 1; j < 20; j++)
{
for (int i = 0; i <= n; i += 1)
{
up[i, j] = up[up[i, j - 1], j - 1];
}
}
// Calculate the maximum number of elements in a good
// segment using binary lifting
for (int i = 0; i < n; i++)
{
int currIndex = i;
for (int j = 19; j >= 0; j--)
{
if ((k & (1 << j)) != 0)
{
currIndex = up[currIndex, j];
}
}
maxGoodSegment = Math.Max(maxGoodSegment, currIndex - i);
}
// Output the result for the current test case
return maxGoodSegment;
}
public static void Main(string[] args)
{
int n = 5, k = 2, s = 5;
List<int> arr = new List<int> { 1, 3, 2, 1, 5 };
Console.WriteLine(Solve(n, k, s, arr));
}
}
JavaScript
// Javascript code for the above approach
const MAX_N = 100005;
const up = Array.from({
length: MAX_N + 5
}, () => Array.from({
length: 20
}, () => 0))
function solve(n, k, s, arr) {
// Array to store nums array, initialized with 0
const nums = Array(n).fill(0);
let currSum = 0;
let maxGoodSegment = 0;
// Calculate the right boundaries of segments
for (let i = 0, j = 0; i < n; i++) {
while (j < n && currSum + arr[j] <= s) {
currSum += arr[j];
j++;
}
up[i][0] = j; // Store the right boundary of the current segment
currSum -= arr[i]; // Move the left boundary of the segment
}
up[n][0] = n; // Set the right boundary of the last element
// Precompute the right boundaries for each power of 2 using binary lifting
for (let j = 1; j < 20; j++) {
for (let i = 0; i <= n; i += 1) {
up[i][j] = up[up[i][j - 1]][j - 1];
}
}
// Calculate the maximum number of elements in a good segment using binary lifting
for (let i = 0; i < n; i++) {
let currIndex = i;
for (let j = 19; j >= 0; j--) {
if ((k & (1 << j)) != 0) {
currIndex = up[currIndex][j];
}
}
maxGoodSegment = Math.max(maxGoodSegment, currIndex - i);
}
return maxGoodSegment;
}
// Example input
const n = 5,
k = 2,
s = 5;
const arr = [1, 3, 2, 1, 5];
// Output the result for the current test case
console.log(solve(n, k, s, arr));
// This code is contributed by ragul21
Time complexity: O(n + n * log(k)), where n is the size of the input array and k is the given parameter.
Auxiliary space: O(n * log(n)).
Similar Reads
Longest Subarray with an Extra 1 Given a binary array arr[], the task is to find the length of the longest subarray having count of 1s exactly one more than count of 0s. Examples: Input: arr[] = [0, 1, 1, 0, 0, 1]Output: 5Explanation: The subarray from index 1 to 5, that is [1, 1, 0, 0, 1] has exactly one more 1s than 0s.Input: arr
10 min read
Longest Subarray with sum differences ⤠K Given a sorted array arr[] of size N, the task is to find the length of the longest subarray and print the subarray such that the sum of the differences of the maximum element of the chosen subarray with all other elements of that same subarray is ⤠K.i.e. â(amax-ai) ⤠K, for that given subarray. Ex
7 min read
Longest subarray with GCD greater than 1 Given an array arr[] consisting of N integers, the task is to find the maximum length of subarray having the Greatest Common Divisor (GCD) of all the elements greater than 1. Examples: Input: arr[] = {4, 3, 2, 2}Output: 2Explanation:Consider the subarray {2, 2} having GCD as 2(> 1) which is of ma
15+ min read
Longest increasing subarray Given an array containing n numbers. The problem is to find the length of the longest contiguous subarray such that every element in the subarray is strictly greater than its previous element in the same subarray. Time Complexity should be O(n). Examples: Input : arr[] = {5, 6, 3, 5, 7, 8, 9, 1, 2}
15+ min read
Longest Subarray with 0 Sum Given an array arr[] of size n, the task is to find the length of the longest subarray with sum equal to 0.Examples:Input: arr[] = {15, -2, 2, -8, 1, 7, 10, 23}Output: 5Explanation: The longest subarray with sum equals to 0 is {-2, 2, -8, 1, 7}Input: arr[] = {1, 2, 3}Output: 0Explanation: There is n
10 min read