Reputation: 21
I was recently asked this question in an interview,
Given an array of non-negative integers find the maximum cumulative sum that could be obtained such that the length of all the participating subarray is a prime number. I tried to come up with a solution for this using Dynamic Programming but unfortunately could not.
Eg: If the array is [9,8,7,6,5,4,3,1,2,2] it should return 46 (sum of the subarray [9,8,7,6,5,4,3] of length 7 and [2,2] of length 2). You cannot combine [9,8,7,6,5,4,3] and [1,2,2] since it would result in a contiguous subarray (idempotency) of length 10 which is non prime.
Can anyone explain how to solve such problems using DP? Thanks.
Upvotes: 2
Views: 1089
Reputation: 23945
How about something like this (approximately) O(n * n / log n)
time, O(n)
space, DP?
Let f(i)
represent the greatest sum up to index i
where a[i]
is either excluded from a contiguous subset or is the last of a subset of prime length. Then:
f(i) = sum(a[0]...a[i]) if (i + 1) is prime, otherwise
max(
// a[i] excluded
f(i-1),
f(i-2),
// a[i] is last of a subset
sum(a[i - primes[j] + 1]...a[i]) + f(i - primes[j] - 1)
for primes[j] <= i
)
(Summing the intervals can be done in O(1)
time with O(n)
preprocessing of prefix-sums.)
Upvotes: 1
Reputation: 1575
Since others have solved the problem for non-negative integers.
But if you have -ve numbers also, then also this algorithm will work. I think you have to slightly tweak Kadane's Algo.
Following are the changes for modified Kadane's Algo. All lines marked ** are changes.
Initialize:
max_so_far = 0
max_ending_here = 0
** MAX_SO_FAR_FOR_PRIMES =0
** SUB_ARRAY_SIZE = 0
Loop for each element of the array
max_ending_here = max_ending_here + a[i]
** SUB_ARRAY_SIZE = SUB_ARRAY_SIZE + 1 // since a[i] included in subarray, increase sub_array_size
if(max_ending_here < 0)
max_ending_here = 0
** SUB_ARRAY_SIZE = 0
if(max_so_far < max_ending_here)
max_so_far = max_ending_here
** if(MAX_SO_FAR_FOR_PRIMES < max_ending_here && isPrime(SUB_ARRAY_SIZE)) // comparing when SUB_ARRAY_SIZE is Prime.
** MAX_SO_FAR_FOR_PRIMES = max_ending_here.
return MAX_SO_FAR_FOR_PRIMES
Basically, take one more variable MAX_SO_FAR_FOR_PRIMES
, which keeps the maximum sum subarray for prime sized subarray so far.
Also store the SUB_ARRAY_SIZE
, which stores the size of the sub-array anytime during looping.
Now just compare you MAX_SO_FAR_FOR_PRIMES
with your max_ending_here
whenever the SUBARRAY_SIZE
is prime. And update `MAX_SO_FAR_FOR_PRIMES1 accordingly.
Upvotes: 0
Reputation: 3541
What you can do:
This works because of the constraint that all integers are positive, it would not work otherwise.
Basically something like this (very roughly, in pseudo-python, obviously not tested):
input_list = (8, 1, 3, 4, 5, 2)
list_size = len(input_list)
while (list_size):
if (is_prime(list_size)):
window_size = list_size
break
list_size--
max_sum = -1
for i in xrange(0, list_size - window_size):
current_sum = sum(input_list[i:i+window_size])
if (max_sum < current_sum):
max_sum = current_sum
print max_sum
Upvotes: 1