Efficient way to solve subset sum variation - java

Given an integer array, find the maximum number of sums of adjacent elements that are divisible by n.
Example 1:
input: long[] array = [1, 2, 3], n = 7
output: 0
Example 2:
input: long[] array = [1, 2, 4], n = 7
output: 1
Example 3:
input: long[] array = [2, 1, 2, 1, 1, 2, 1, 2], n = 4
output: 6
Constraints:
array.length = 50000
array[index] <= 2^31 - 1
n <= 2^31 - 1
Currently, this is my code:
public static int maxSums(long[] array, long n) {
int count = 0;
if (array.length == 1 && array[0] == n) {
return 1;
} else {
for (int i = 0; i < array.length; i++) {
long sum = 0;
for (int j = i; j < array.length; j++) {
sum += array[j];
if (sum % n == 0) {
count++;
}
}
}
}
return count;
}
which is essentially the window sliding technique. However, this code runs with time complexity O(n^2) which is pretty slow, and results in Apex CPU Time Limit Exceeded towards the higher end of the constraints. Is there a faster way to solve this?

An approach I just thought of is O(n*m), where n is the actual n parameter and m is the array length.
The algorithm remembers for every subsequence up to the current index what reminder the sequence sum has. This information is stored inside the array called currentMod.
When iterating over the input array this currentMod is updated. We simply add to each possible modulo value of iteration i-1 the value of the input array at index i. The updated array includes the number of subsequence sums ending at index i for each possible reminder: 0, 1, 2 up to n-1.
The element first element of tmpMod at index i includes the number of subsequences that end at index i and have a sum divisible by n. Therefore, we add them to our final result.
Here is the algorithm:
public static int maxSums(int[] array, int n) {
int[] currentMod = new int[n];
int count = 0;
for (int i = 0; i < array.length; i++) {
// Add +1 to 0 remainder as a new sequence can start at every index which has sum 0
currentMod[0] += 1;
int[] tmpMod = new int[n];
for (int j = 0; j < currentMod.length; j++) {
// For every subsequence reminder of i-1 calculate the reminders of adding element i to every subsequence
tmpMod[(j + array[i]) % n] += currentMod[j];
}
// Add number of subsequence sums that divide by n with remainder 0 to result
count += tmpMod[0];
currentMod = tmpMod;
}
return count;
}
P.S.: This algorithm is not strictly better/worse than yours. It depends on another input value. This means it depends on your inputs what is more efficient. My algorithm is only better for a case with large arrays and low n values.
EDIT: After a lot of thinking and testing I think I found a good solution. It is O(n) in time complexity. It is also O(n) in space complexity as there can be at most n different remainders with n values in the array.
The algorithm keeps track of the current remainder, which is dividable by the input n from the start. For each new subsequence, we add the 1 at the current remainder. In this way, we already define which total sum (mod n) we need that the subsequence is dividable by n.
public static int maxSums(int[] array, int n) {
Map<Integer, Integer> currentMod = new HashMap<Integer, Integer>();
int count = 0;
int currentZero = 0;
for (int val : array) {
currentMod.put(currentZero, currentMod.getOrDefault(currentZero, 0) + 1);
currentZero = (currentZero + val) % n;
count += currentMod.getOrDefault(currentZero, 0);
}
return count;
}
Also, some comparisons to show that it should work out:
len(array)=50000 and n=1000:
Your method: 11704 ms
My old one: 188 ms
My new one: 13 ms
len(array)=50000 and n=1000000:
Your method: 555 ms
My old one: stopped after 2 minutes
My new one: 6 ms

Related

Find the sum of maximum difference of all possible subarrays

Find the sum of maximum difference possible from contiguous subset of a given array.
We are given an array arr[] of n non-negative integers (repeated elements allowed), find out the sum of maximum difference possible from contiguous subsets of the given array.
Suppose max(s) represents the maximum value in any subset ‘s’ whereas min(s) represents the minimum value in the set ‘s’. We need to find the sum of max(s)-min(s) for all possible subsets.
Input : arr[] = {1, 2, 3}
Output : result = 4
Explanation :
All possible subset and for each subset s,
max(s)-min(s) are as :
SUBSET | max(s) | min(s) | max(s)-min(s)
{1, 2} | 2 | 1 | 1
{2, 3} | 3 | 2 | 1
{1, 2, 3} | 3 | 1 | 2
Total Difference sum = 4
Note : max(s) - min(s) for all subset with
single element must be zero.
Constraints:
Array size can be from 1 to 10 power 5, also each element in array can be from 1 to 10 power 5.
This is the code taken from here, but this code checks all possible subsets instead of contiguous subsets:
public static int MOD = 1000000007;
// function for sum of max min difference
public static long maxMin (int arr[], int n)
{
// sort all numbers
Arrays.sort(arr);
// iterate over array and with help of
// horner's rule calc max_sum and min_sum
long min_sum = 0, max_sum = 0;
for (int i = 0; i < n; i++)
{
max_sum = 2 * max_sum + arr[n - 1 - i];
max_sum %= MOD;
min_sum = 2 * min_sum + arr[i];
min_sum %= MOD;
}
return (max_sum - min_sum + MOD)%MOD;
}
So how to get only contiguous subsets and solve this with less time complexity.
You can do this in O(n) time and space.
The technique is to use the algorithm for all nearest smaller values. First, break the problem into two parts:
Find the sum of all subarray maximums
Find the sum of all subarray minimums, and subtract this from the first sum.
The solution for both problems is identical apart from exchanging all occurrences of 'less than' with 'greater than', so I'll describe the minimums case only.
For each element A[i] of the array, you can ask: 'How many subarrays have A[i] as their minimum element?' To deal with duplicates, assume we always take the rightmost occurrence of a minimum element within a subarray as the 'representative' element.
The question transforms to finding how far to the left of A[i] we can go before seeing an element strictly smaller than A[i], and how far to the right of A[i] we can go before seeing an element as small as A[i]. Multiply these two distances to get all possible choices of left and right endpoints among subarrays that have A[i] as their minimum element. We can find both of these directly with the 'all nearest smaller values' algorithm, and solve the rest of the problem like so (pseudocode):
1. For each position i in the array A, let previous_smaller[i]
be the largest index j such that A[j] < A[i] and 0 <= j < i,
or -1 if there is no such index.
2. For each position i in the array A, let next_smaller_or_equal[i]
be the smallest index j such that A[j] <= A[i] and i < j < n,
or n if there is no such index.
3. Return the sum over all i, 0 <= i < n, of
(A[i] *
(next_smaller_or_equal[i] - i) *
(i - previous_smaller[i]))
There are several implementations of all nearest smaller values in the answers to this question, for example, and pseudocode in the Wikipedia article. To find 'next smaller values' instead of 'previous smaller values', simply run the algorithm on a reversed array A (or just traverse A in reverse order, from A[n-1] down to A[0]).
Sample implementation of the whole algorithm (in Python):
def max_difference_sum(A: List[int]) -> int:
"""Given an array of integers A, compute the
sum over all subarrays B of max(B) - min(B)
by using nearest smaller values"""
n = len(A)
# Convention to take the rightmost min or max in each subarray.
previous_smaller = list(range(n))
next_smaller_or_equal = list(range(n))
previous_larger = list(range(n))
next_larger_or_equal = list(range(n))
# Compute the previous larger and smaller in a single loop.
for i in range(n):
j = i - 1
while j >= 0 and A[j] >= A[i]:
j = previous_smaller[j]
previous_smaller[i] = j
j = i - 1
while j >= 0 and A[j] <= A[i]:
j = previous_larger[j]
previous_larger[i] = j
for i in reversed(range(n)):
j = i + 1
while j < n and A[j] > A[i]:
j = next_smaller_or_equal[j]
next_smaller_or_equal[i] = j
j = i + 1
while j < n and A[j] < A[i]:
j = next_larger_or_equal[j]
next_larger_or_equal[i] = j
max_sums = sum(A[i]
* (next_larger_or_equal[i] - i)
* (i - previous_larger[i])
for i in range(n))
min_sums = sum(A[i]
* (next_smaller_or_equal[i] - i)
* (i - previous_smaller[i])
for i in range(n))
return max_sums - min_sums
Let's use the induction method.
Assume we solved the problem somehow for the array of size N and know the desired sum.
Let's find the solution if the element A[n+1] is added.
We need to calculate the sums only for all sequences that include A[n+1].
A[0], A[1], A[2], ..., A[n+1]
A[1], A[2], ..., A[n+1]
...
A[n], A[n+1]
All other contiguous subsets were calculated at the previous step somehow.
In order to calculate their minimums and maximums let's examine them in the reverse order.
A[n+1], A[n]
A[n+1], A[n], A[n-1]
...
A[n+1], A[n], ..., A[0]
This gives us an ability to iterate them and find their extremes in a single loop.
So the code is
int a[] = {1, 2, 3};
long sum = 0;
for (int i = 1; i < a.length; i++) {
int min = a[i];
int max = a[i];
for (int j = i - 1; j >= 0; j--) {
int current = a[j];
if (current < min) min = current;
if (current > max) max = current;
sum += max - min;
}
}
System.out.println("Sum = " + sum);
The solution complexity is O(n^2) as there are two nested loops.
You can achieve this using stream:
public static int difference(int[] arr) {
int size = arr.length;
return IntStream.range(0, size)
.flatMap(i -> IntStream.range(i + 1, size)
.mapToObj(j -> Arrays.stream(arr, i, j + 1).summaryStatistics())
.mapToInt(stat -> stat.getMax() - stat.getMin()))
.sum();
}
Alternatively, as noticed by #kcsquared, you can use 2 stream, one for max sum and the other for min sum, and subtract them. This approach also avoids unnecessary boxing and unboxing.
public static int difference2(int[] arr) {
int size = arr.length;
int max = IntStream.range(0, size)
.flatMap(i -> IntStream.range(i + 1, size)
.map(j -> Arrays.stream(arr, i, j + 1).max().getAsInt()))
.sum();
int min = IntStream.range(0, size)
.flatMap(i -> IntStream.range(i + 1, size)
.map(j -> Arrays.stream(arr, i, j + 1).min().getAsInt()))
.sum();
return max - min;
}
Since the proposed partial solution is already paying the sort cost, an initial time optimization could pre transform the input arr to a list of (i, arr[i]), then sort by the arr[i]values & in the for loop skip over sorted_tuple_arr with non consecutive i values.

Find the pair (i,j) such that i<j and and (a[i] + a[j]) is maximum

Given an unsorted array – arr find a pair arr[i] and arr[j] such that
arr[i] < arr[j] & i<j and (arr[i] + arr[j]) is maximum.
Expected time complexity – O(n)
For array a = {4, 1, 3, 2, 5, 3}
pair is (4, 5).
Here is the code I've tried..
void findPair(int[] a){
int n = a.length;
int max = a[0];
int secondMax = Integer.MIN_VALUE;
for(int i=1; i<n; i++){
if(a[i]>max){
secondMax = max;
max = a[i];
}
}
if(secondMax == Integer.MIN_VALUE){
System.out.println("-1 -1");
}
else{
System.out.println(secondMax+" "+max);
}
}
Here's a solution using a stack. The idea is that the stack always contains a descending sequence, such that for each number you look at, it can be paired with the largest number in the stack lower than it.
It's safe to pop the numbers off as you use them, because e.g. if you have a 6 and the top of the stack is 3, there is no need to keep the 3 around in case it can be paired with a bigger number; if there's a 7 later, you would wait to pair it with the 6 instead of the 3.
public void solution(int[] arr) {
Stack<Integer> stack = new Stack<>();
int bestX = -1, bestY = -1, bestSum = -1;
for(int y : arr) {
while(!stack.isEmpty() && stack.peek() < y) {
int x = stack.pop();
if(x + y > bestSum) { bestX = x; bestY = y; bestSum = x + y; }
}
stack.push(y);
}
System.out.println(bestX + " " + bestY);
}
The time complexity is O(n) despite the nested loop, because the inner loop always pops from the stack, and each element is only pushed once so it can only be popped once.
I thought about your question a lot and I think I found an acceptable solution.
You should split the array into subarrays starting from the end of the array (right side). Building the sub arrays is in iterative manner. You start with the right-most number and you add to the subarray all the numbers before him that are lower than him. The iteration goes to the next subarray when you reach a number which is bigger/equal to the right-most number in the subarray.
Example:
Your array is: {1,7,3,4,5,4,6,2}
Output should be: (5,6)
The splitting should be:
{{1, 7}, {3, 4, 5, 4, 6}, {2}}
<--(3) <--(2) <--(1)
You start from the last index with the value of 2. The number before him is 6 so that's the end of the first subarray. Next you start with 6, all the numbers before him until 7 are lower than 6 so you add them to that subarray. The last subarray starts with 7 and adds 1. See arrows for clarification.
Next, check within each subarray which number from left to the right-most number is max and mark it for possible pair with the right-most number.
In our example it would be: (1,7), (5,6).
There are only two options because {2} has only 1 variable. In the subarray with 6 as right-most the max number is 5 and in the subarray with 7 as right-most 1 is the only other number so it is also the max.
If no pair is found, return "no possible pair found".
Finally, check sum and return biggest pair: (5,6)
1+7 = 8 < 5+6 = 11
Why is this O(n) ?
You scan the array once for splitting: O(n)
Each subarray of size d you scan for max value: O(d)
Sum of all subarrays scanning: O(n)
Total: O(n)
I'm not strong in Java so my code can be written in Python and the conversion should be easy (because Python is easy!). If you wish for Python code, let me know and I'll write some for you. Also, I can explain more why this algorithm works (If not fully understood).
DISCLAIMER: Solution is O(n^2), not O(n) as required by the OP
What about using 2 nested loops:
i from 0 to a.length
j from i+1 to a.length
This ensures that i<j
Then have an if to ensure that a[i]<a[j] and find the max
int currentMax = -1;
int foundI = -1;
int foundJ = -1;
for(int i=0; i<a.length; i++) {
for(int j=i+1; j<a.length; j++) {
if(a[i] < a[j] && a[i] + a[j] > currentMax) {
currentMax = a[i] + a[j];
foundI = i;
foundJ = j;
}
}
}
Output:
System.out.println("i:" + foundI);
System.out.println("j:" + foundJ);
System.out.println("a[i]:" + a[foundI]);
System.out.println("a[j]:" + a[foundJ]);
System.out.println("sum:" + currentMax);
i:0
j:4
a[i]:4
a[j]:5
sum:9

Count numbers with same digits in a sorted int array in O(log n) time

I came across an interview question that required the candidate to count all numbers in an array with the same digits.
for example:
Count all numbers that share the same digits with int input = 394
int[] arr = {1, 14, 101, 349, 439, 745, 934}
the function would return 3, since 439, 934, 349 share the same digits.
The question is how do you solve this in O(log n) time? Im still new to the Big O concept and apart from O(n) and O(n^2)... i am having trouble understanding how to archieve O(log n).
My first thought was as follows:
I would calculate the sum of digits of all elements in the array. If the sum is equal they contain of the same of the digits as the input number.
int counter = 0;
while (num > 0) {
int digitSum += num % 10;
num = num / 10;
}
for(int i = 0; i < arr.length; i++) {
int k = arr[i];
while (k > 0) {
int sumOfDigits += k % 10;
k = k/10;
}
if(sumOfDigits == digitSum) {
counter++;
}
}
I know this would take at least O(n) time but im having trouble finding a better solution.
The best answer was given by Andy Turner and JB Nizet but unfortunately only as a comment:
For this to work we must assume: the size of the input number is bounded, the integers in the array are disjoint and n is the number of elements in the array.
Compute all permutations of the input number digits. Some of the permutations may be the same if the number has repeated digits, take them only once. This takes O(1) time and the number of permutations is also O(1).
For each permutation look up the corresponding number in the array using binary search and count all the hits. This takes O(log n).
In total you get a run time of O(log n).
Note that this is only practical if the bound on the input number is rather low. If the input number can have say 20 digits it is much better to use an O(n) method unless n is really huge.
You can preprocess the array to construct a Map, by "string representing the sorted digits" of the numbers in an array that map to that normalized representation. After that step, individual lookups are O(1) or O(log(n)) depending on the map chosen. It doesn't even matter how many numbers match, because you're just returning a preconstructed array.
So the lookup can indeed be made very fast. But only if you either discount the preprocessing step, or amortize it over many lookups.
This solution is almost O(n) as number of digit in the input is very small compare to the given array size (n).
Idea is to get the minimum possible number from each element and compare with the corresponding value of the input number
public static void main(String []args){
int input = 394;
int[] arr = {1, 14, 101, 349, 439, 745, 934};
int ans = 0;
int hold = getMin(input);
for(int i = 0; i < arr.length; i++)
{
if(hold == getMin( arr[i] ))
{
ans++;
}
}
System.out.println(ans);
}
public static int getMin(int n)
{
int hold[] = new int[10];
while( n > 0)
{
hold[n % 10]++;
n /= 10;
}
int ans = 0;
for(int i = 0; i < hold.length; i++)
{
while(hold[i] > 0)
{
ans = ans * 10 + i;
hold[i]--;
}
}
return ans;
}

JAVA: Method that takes an int "n" as input, and returns an array that contains the first n prime numbers

Here is what I got so far
public static int[] firstPrimeNumbers(int n) {
int[] k = new int[n];
int m = 0;
for (int i = 0; i < n; i++) {
if (isPrime(i)) {
k[m] = i;
m++;
}
}
return k;
}
Problem is, when I try to print the resulting array, I get a bunch of 0's at the end. For example when I took n = 10, the program printed
2, 3, 5, 7, 0, 0, 0, 0, 0, 0
Hows that even possible? What am I doing wrong?
What happens here is fairly easy.
k has size 10 and initially filled with zeros.
Then you check the first 10 natural numbers and check whether they are prime.
So for each non-prime number you should get a 0
Maybe replace i<n by m<n but that depends a bit on what you want to achieve.
You should modify your for loop. What you are doing is actually returning in an array of n elements the primitive numbers less than n
public static int[] firstPrimeNumbers(int n) {
int[] k = new int[n];
int nr = 2;
int m = 0;
while(m<n){
if(isPrime(nr)){
k[m] = nr;
m++;
}
nr++;
}
return k;
}
You are just counting until i == n (so only looking at number up to n) - you need to keep incrementing i until m == n so you are considering whether numbers > n are prime.
If you used better variable names like nextPrimeIndex or primesFound instead of m this would probably be easier to spot.

in Java, design linear algorithm that finds contiguous subsequence with highest sum

this is the question, and yes it is homework, so I don't necessarily want anyone to "do it" for me; I just need suggestions: Maximum sum: Design a linear algorithm that finds a contiguous subsequence of at most M in a sequence of N long integers that has the highest sum among all such subsequences. Implement your algorithm, and confirm that the order of growth of its running time is linear.
I think that the best way to design this program would be to use nested for loops, but because the algorithm must be linear, I cannot do that. So, I decided to approach the problem by making separate for loops (instead of nested ones).
However, I'm really not sure where to start. The values will range from -99 to 99 (as per the range of my random number generating program).
This is what I have so far (not much):
public class MaxSum {
public static void main(String[] args){
int M = Integer.parseInt(args[0]);
int N = StdIn.readInt();
long[] a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = StdIn.readLong();}}}
if M were a constant, this wouldn't be so difficult. For example, if M==3:
public class MaxSum2 {
public static void main(String[] args){
int N = StdIn.readInt(); //read size for array
long[] a = new long[N]; //create array of size N
for (int i = 0; i < N; i++) { //go through values of array
a[i] = StdIn.readLong();} //read in values and assign them to
//array indices
long p = a[0] + a[1] + a[2]; //start off with first 3 indices
for (int i =0; i<N-4; i++)
{if ((a[i]+a[i+1]+a[1+2])>=p) {p=(a[i]+a[i+1]+a[1+2]);}}
//if sum of values is greater than p, p becomes that sum
for (int i =0; i<N-4; i++) //prints the subsequence that equals p
{if ((a[i]+a[i+1]+a[1+2])==p) {StdOut.println((a[i]+a[i+1]+a[1+2]));}}}}
If I must, I think MaxSum2 will be acceptable for my lab report (sadly, they don't expect much). However, I'd really like to make a general program, one that takes into consideration the possibility that, say, there could be only one positive value for the array, meaning that adding the others to it would only reduce it's value; Or if M were to equal 5, but the highest sum is a subsequence of the length 3, then I would want it to print that smaller subsequence that has the actual maximum sum.
I also think as a novice programmer, this is something I Should learn to do. Oh and although it will probably be acceptable, I don't think I'm supposed to use stacks or queues because we haven't actually covered that in class yet.
Here is my version, adapted from Petar Minchev's code and with an important addition that allows this program to work for an array of numbers with all negative values.
public class MaxSum4 {
public static void main(String[] args)
{Stopwatch banana = new Stopwatch(); //stopwatch object for runtime data.
long sum = 0;
int currentStart = 0;
long bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
int M = Integer.parseInt(args[0]); // read in highest possible length of
//subsequence from command line argument.
int N = StdIn.readInt(); //read in length of array
long[] a = new long[N];
for (int i = 0; i < N; i++) {//read in values from standard input
a[i] = StdIn.readLong();}//and assign those values to array
long negBuff = a[0];
for (int i = 0; i < N; i++) { //go through values of array to find
//largest sum (bestSum)
sum += a[i]; //and updates values. note bestSum, bestStart,
// and bestEnd updated
if (sum > bestSum) { //only when sum>bestSum
bestSum = sum;
bestStart = currentStart;
bestEnd = i; }
if (sum < 0) { //in case sum<0, skip to next iteration, reseting sum=0
sum = 0; //and update currentStart
currentStart = i + 1;
continue; }
if (i - currentStart + 1 == M) { //checks if sequence length becomes equal
//to M.
do { //updates sum and currentStart
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
//if sum or a[currentStart]
} //is less than 0 and currentStart<=i,
} //update sum and currentStart again
if(bestSum==0){ //checks to see if bestSum==0, which is the case if
//all values are negative
for (int i=0;i<N;i++){ //goes through values of array
//to find largest value
if (a[i] >= negBuff) {negBuff=a[i];
bestSum=negBuff; bestStart=i; bestEnd=i;}}}
//updates bestSum, bestStart, and bestEnd
StdOut.print("best subsequence is from
a[" + bestStart + "] to a[" + bestEnd + "]: ");
for (int i = bestStart; i<=bestEnd; i++)
{
StdOut.print(a[i]+ " "); //prints sequence
}
StdOut.println();
StdOut.println(banana.elapsedTime());}}//prints elapsed time
also, did this little trace for Petar's code:
trace for a small array
M=2
array: length 5
index value
0 -2
1 2
2 3
3 10
4 1
for the for-loop central to program:
i = 0 sum = 0 + -2 = -2
sum>bestSum? no
sum<0? yes so sum=0, currentStart = 0(i)+1 = 1,
and continue loop with next value of i
i = 1 sum = 0 + 2 = 2
sum>bestSum? yes so bestSum=2 and bestStart=currentStart=1 and bestEnd=1=1
sum<0? no
1(i)-1(currentStart)+1==M? 1-1+1=1 so no
i = 2 sum = 2+3 = 5
sum>bestSum? yes so bestSum=5, bestStart=currentStart=1, and bestEnd=2
sum<0? no
2(i)-1(currentStart)+1=M? 2-1+1=2 so yes:
sum = sum-a[1(curentstart)] =5-2=3. currentStart++=2.
(sum<0 || a[currentStart]<0)? no
i = 3 sum=3+10=13
sum>bestSum? yes so bestSum=13 and bestStart=currentStart=2 and bestEnd=3
sum<0? no
3(i)-2(currentStart)+1=M? 3-2+1=2 so yes:
sum = sum-a[1(curentstart)] =13-3=10. currentStart++=3.
(sum<0 || a[currentStart]<0)? no
i = 4 sum=10+1=11
sum>bestSum? no
sum<0? no
4(i)-3(currentStart)+1==M? yes but changes to sum and currentStart now are
irrelevent as loop terminates
Thanks again! Just wanted to post a final answer and I was slightly proud for catching the all negative thing.
Each element is looked at most twice (one time in the outer loop, and one time in the while loop).
O(2N) = O(N)
Explanation: each element is added to the current sum. When the sum goes below zero, it is reset to zero. When we hit M length sequence, we try to remove elements from the beginning, until the sum is > 0 and there are no negative elements in the beginning of it.
By the way, when all elements are < 0 inside the array, you should take only the largest negative number. This is a special edge case which I haven't written below.
Beware of bugs in the below code - it only illustrates the idea. I haven't run it.
int sum = 0;
int currentStart = 0;
int bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
for (int i = 0; i < N; i++) {
sum += a[i];
if (sum > bestSum) {
bestSum = sum;
bestStart = currentStart;
bestEnd = i;
}
if (sum < 0) {
sum = 0;
currentStart = i + 1;
continue;
}
//Our sequence length has become equal to M
if (i - currentStart + 1 == M) {
do {
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
}
}
I think what you are looking for is discussed in detail here
Find the subsequence with largest sum of elements in an array
I have explained 2 different solutions to resolve this problem with O(N) - linear time.

Categories

Resources