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;
for ( int i = 0, j = 0; i < n; i++) {
while (j < n && currSum + arr[j] <= s) {
currSum += arr[j];
j++;
}
up[i][0] = j;
currSum -= arr[i];
}
up[n][0] = n;
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];
}
}
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);
}
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<Integer> nums = new Vector<>(n);
for ( int i = 0 ; i < n; i++) {
nums.add( 0 );
}
int currSum = 0 ;
int maxGoodSegment = 0 ;
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;
currSum -= arr.get(i);
}
up[n][ 0 ] = n;
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 ];
}
}
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) {
int n = 5 , k = 2 , s = 5 ;
Vector<Integer> arr = new Vector<>(Arrays.asList( 1 , 3 , 2 , 1 , 5 ));
System.out.println(solve(n, k, s, arr));
}
}
|
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
for i in range (n):
j = i
while j < n and curr_sum + arr[j] < = s:
curr_sum + = arr[j]
j + = 1
up[i][ 0 ] = j
curr_sum - = arr[i]
up[n][ 0 ] = n
for j in range ( 1 , 20 ):
for i in range (n + 1 ):
up[i][j] = up[up[i][j - 1 ]][j - 1 ]
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)
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;
for ( int i = 0, j = 0; i < n; i++)
{
while (j < n && currSum + arr[j] <= s)
{
currSum += arr[j];
j++;
}
up[i, 0] = j;
currSum -= arr[i];
}
up[n, 0] = n;
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];
}
}
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)
{
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
const MAX_N = 100005;
const up = Array.from({
length: MAX_N + 5
}, () => Array.from({
length: 20
}, () => 0))
function solve(n, k, s, arr) {
const nums = Array(n).fill(0);
let currSum = 0;
let maxGoodSegment = 0;
for (let i = 0, j = 0; i < n; i++) {
while (j < n && currSum + arr[j] <= s) {
currSum += arr[j];
j++;
}
up[i][0] = j;
currSum -= arr[i];
}
up[n][0] = n;
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];
}
}
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;
}
const n = 5,
k = 2,
s = 5;
const arr = [1, 3, 2, 1, 5];
console.log(solve(n, k, s, arr));
|
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)).
Share your thoughts in the comments
Please Login to comment...