**** Problem: longest sub-array having sum at most k?
If all the array elements are positive then this problem is easily solvable using two pointers. for ex:
Let's say the array look like this a=[10,30,40,7,1] and k=48.
Solution: We keep two pointers l and r and we will always expand our sub-array with rth pointer and shrink from lth pointer
Iterations:
l=0,r=0 a[l---r]= 10 since 10<=48 we update our ans as 1 and we increment the rth pointer l=0,r=1 a[l---r]= [10,30] since 10+30<=48 we update our ans as 2 and we again increment the rth pointer. l=0,r=2 a[l---r]= [10,30,40] since 10+30+40>48 we will shrink our window by incrementing the lth pointer untill sum<=k. ie [10,30,40] to [30,40] still sum>k so we reduce the window to [40] l=2,r=2 a[l----r]=40
l=2,r=3 a[l---r]= [40,7] since 40+7<=48 we increment the rth pointer l=2,r=4 a[l---r]= [40,7,1] since 40+7+1<=48 we update our answer as 3.
This problem is also covered in the two pointers section in code forces edu.
But the problem with this algorithm is it does not work if the array contains negative elements because we are not assure that shrinking the window size always make our sum less positive as our lth pointer can be very big negative value as well. Thus removing the lth pointer here makes our sum more positive.
for ex: a=[-5,-4,-3,16,1,-6,-4,50] and k=3
In above example we can clearly see that the subarray[0,6]=[-5,-4,-3,16,1,-6,-4] is longest having sum<=3
But if we go by above algorithm we will not get this as our answer because when our rth pointer reaches 16 ie a=[-5,-4,-3,16] sum=4>k so we will shrink our window to [-4,-3,16] sum=9>k again we will shrink window to [-3,16] still sum>k.At the end we will be left with empty window ie l=r=3.
Now here we will not get accurate answer as l is increased to 3.
For this problem the only solution that comes into mind is O(N*N) ie trying all poss sub-arrays and checking whether sum<=k and finding largest.
If anyone have a better way of solving this please suggest.Thanks in advance.
We can simply make suffix minimum over prefix sums (to avoid segment tree), ( suff[i] means min(pre[i],pre[i+1]...pre[n]) ). Then for every pre[i], just binary search over suffix minimum to find highest index j (j>=i) such that suff[j]<=k+pre[i]. (Note that suffix minimum will be an increasing sequence.)
Thanks for the explanation.
Suppose the optimal interval is $$$[L \ldots R]$$$. Then there can be no index $$$x \gt R$$$ with $$$\sum_{i \in [R+1 \ldots x]} a_i \leq 0$$$, since otherwise $$$[L \ldots x]$$$ would be a better interval. You can precalculate the values $$$R$$$ that satisfy this condition in $$$O(n)$$$ and then the two-pointers/sliding-window idea will just work: Whenever you want to increase $$$R$$$, you can increase it all the way to the next value $$$R'$$$ that satisfies the condition, and doing so cannot decrease the sum on the current interval because otherwise $$$x=R'$$$ would disprove the condition for $$$R$$$.
By precalculating do you mean this suffix[i------n]<=0 or suffix[i-----n]>0.
I am not able to understand your approach. At any point, we will check for the maximum R such that afterward including the R+1 ----n index would not work. Please Explain.
I think you can do it in
O(n)
with an ok constant.s[0] = 0
s[i] = v[1] + .. + v[i]
u[i] = s[i] - k
For each
i
I am interested in the smallestj < i
such ass[j] >= u[i]
(if it exists).If I have two indices
j
,z
ins[]
,j < z
, both satisfying the request fori
:j < i
,s[j] >= u[i]
andz < i
,s[z] >= u[i]
,then I would always prefer
j
overz
, because it would give me a longer subsequence.Radix sort in increasing manner
u[1], .., u[n]
.Now go with
j = [0, n]
throughs[]
, and for eachj
advance as much as possible intou[]
(from the last point you stopped at withj-1
).Basically, pick out as many small
u[]
s as possible withs[0] = 0
, then pick out the remaining ones withs[1]
, ...I hope that the following code is correct: https://ide.geeksforgeeks.org/1eFqH6CvTg
Do you have a problem link? Thank you!