Maximum sum of non consecutive elements (Dynamic Programming) - algorithm

Given an array of positive integers, what's the most efficient
algorithm to find non-consecutive elements from this array which, when
added together, produce the maximum sum?
The dynamic programming solution is to use an auxiliary array maxSum holding the max sum up until that particular index. We start by setting the first 2 indices of the array, and fill the rest of the array with max(array[i]+maxSum[i-2], maxSum[i-1]).
I understand that we cannot add adjacent elements, but I am struggling to understand how the above solution takes into consideration that it is possible for the the previous element in maxSum[i] to not be the result of summing with array[i].
For example:
index: 0 1 2 3 4
array: 3 5 -7 8 10
maxSum: 3 5 5 _
We see that maxSum[2] is not a result of summing with array[2].
To find maxSum[3] = max(array[3]+maxSum[1], maxSum[2]), but why don't we consider maxSum[2] + array[3]? Since it is possible for maxSum[2] to not consist of the adjacent array[2] value.

how does the above solution take into consideration that it is possible for the previous element in maxSum[i] to not be the result of summing with array[i]?
Simply. If the previous element in maxSum[i] is not to be included in the result of summing with array[i], we can look at maxSum[i - 2]. We do this explicitly in
array[i]+maxSum[i-2]
we compare that against the option of not including array[i], which is
maxSum[i-1]

First all, you might not understand the procedure completely:
For each index i, maxSum represents the max of (sum by including i-th element, sum by excluding i-th element)
maxSum[3] = max(array[3]+maxSum[1], maxSum[2]), because array[3]+maxSum[1] represents the sum if array[3] is taken, and maxSum[2] if array[3] is excluded.

I am assuming you need an explanation of the reasoning, here it is.
Let M[i] be the maximum sum we can obtain by including the first i elements of the array A (with the condition that no two are consecutive). There are two possibilities:
M[i] includes element i. In this case it cannot include element i-1
so M[i]=A[i]+M[i-2]
M[i] does not include element i. In this case M[i]=M[i-1].
Since we don't know if it actually includes i or not we compute both cases and choose the maximum between the two thus
M[i]=max(M[i-1],A[i]+M[i-2])

Related

Make balance bracket with highest score

Question:
Given an array A of integers and a score S = 0. For each place in the array, you can do one of the following:
Place a "(". The score would be S += Ai
Place a ")". The score would be S -= Ai
Skip it
What is the highest score you can get so that the brackets are balanced?
Limits:
|Ai| <= 10^9
Size of array A: <= 10^5
P/S:
I have tried many ways but my best take is a brute force that takes O(3^n). Is there a way to do this problem in O(n.logn) or less?
You can do this in O(n log n) time with a max-heap.
First, remove the asymmetry in the operations. Rather than having open and closed brackets, assume we start off with a running sum of -sum(A), i.e. all closed brackets. Now, for every element in A, we can add it to our running sum either zero, one or two times, corresponding to leaving a closed bracket, removing the closed bracket, or adding an open bracket, respectively. The balance constraint now says that after processing the first k elements, we have:
Made at least k additions, for all integers k,
We make length(A) total additions.
We have added the final element to our sum either zero or one times.
Suppose that after processing the first k elements, we have made k additions, and that we have the maximum score possible of all such configurations. We can extend this to a maximum score configuration of the first k+1 elements with k+1 additions, greedily. We have a new choice going forward of adding the k+1-th element to our sum up to two times, but can only add it at most once now. Simply choose the largest seen element that has not yet been added to our sum two times, and add it to our sum: this must also be a maximum-score configuration, or we can show the old configuration wasn't maximum either.
Python Code: (All values are negated because Python only has a min-heap)
def solve(nums: List[int]) -> int:
"""Given an array of integers, return the maximum sum achievable.
We must add k elements from nums and subtract k elements from nums,
left to right and all distinct, so that at no point have we subtracted
more elements than we have added.
"""
max_heap = []
running_sum = 0
# Balance will be 0 after all loop iterations.
for value in nums:
running_sum -= value # Assume value is subtracted
heapq.heappush(max_heap, -value) # Option to not subtract value
heapq.heappush(max_heap, -value) # Option to add value
# Either un-subtract or add the largest previous free element
running_sum -= heapq.heappop(max_heap)
return running_sum
You can do this in O(n2) time by using a two-dimensional array highest_score, where highest_score[i][b] is the highest score achievable after position i with b open brackets yet to be closed. Each element highest_score[i][b] depends only on highest_score[i−1][b−1], highest_score[i−1][b], and highest_score[i−1][b+1] (and of course A[i]), so each row highest_score[i] can be computed in O(n) time from the previous row highest_score[i−1], and the final answer is highest_score[n][0].
(Note: that uses O(n2) space, but since each row of highest_score depends only on the previous row, you can actually do it in O(n) by reusing rows. But the asymptotic runtime complexity will be the same either way.)

Count unique values in subarrays

Array a*b is given, which contains numbers up to 1e5, and we have to sum the count of unique numbers in every k*k subarray,
there are a-k*b-k subarrays
e.g
1 2 3 4
3 2 4 1
for k=2
subarrays are
{1,2,3,2}(3distinct values)
{2,3,2,4}(3distinct values)
{3,4,4,1}(3distinct values)
output is 9
Is there a faster approach than using a table which stores count of every number ocurrencies in an actaully processed k*k subarray(e.g at index 3 we store count of 3's in a subarray), moving a k*k window by 1 and adding values from right and removing from left, if after incremention value is 1 - increment unique numbers counter; if after decrementation value is 0 - decrement unique numbers counter.
After getting to the end of the row, go 1 down and move in the opposite direction.
Not worried about memory usage,im just looking for a way to do this faster
a == b is an equivalence relation.
Given A the set of elements (your subarray), you can find the equivalence classes of the relation with the method you found:
For each element x in the subarray A you take c[x] which is an int (c array elements all initialized to 0). If this c[x] == 0 then you have a new unique element so c[x]++. Otherwise you increment c[x].
This algorithm is linear to the number of elements in the subarray (obviously you iterate this process for each subarray and sum the results to get what you want).
But time complexity can’t be lower, cause you need to check each element anyway.

Maximum of all possible subarrays of an array

How do I find/store maximum/minimum of all possible non-empty sub-arrays of an array of length n?
I generated the segment tree of the array and the for each possible sub array if did query into segment tree but that's not efficient. How do I do it in O(n)?
P.S n <= 10 ^7
For eg. arr[]= { 1, 2, 3 }; // the array need not to be sorted
sub-array min max
{1} 1 1
{2} 2 2
{3} 3 3
{1,2} 1 2
{2,3} 2 3
{1,2,3} 1 3
I don't think it is possible to store all those values in O(n). But it is pretty easy to create, in O(n), a structure that makes possible to answer, in O(1) the query "how many subsets are there where A[i] is the maximum element".
Naïve version:
Think about the naïve strategy: to know how many such subsets are there for some A[i], you could employ a simple O(n) algorithm that counts how many elements to the left and to the right of the array that are less than A[i]. Let's say:
A = [... 10 1 1 1 5 1 1 10 ...]
This 5 up has 3 elements to the left and 2 to the right lesser than it. From this we know there are 4*3=12 subarrays for which that very 5 is the maximum. 4*3 because there are 0..3 subarrays to the left and 0..2 to the right.
Optimized version:
This naïve version of the check would take O(n) operations for each element, so O(n^2) after all. Wouldn't it be nice if we could compute all these lengths in O(n) in a single pass?
Luckily there is a simple algorithm for that. Just use a stack. Traverse the array normally (from left to right). Put every element index in the stack. But before putting it, remove all the indexes whose value are lesser than the current value. The remaining index before the current one is the nearest larger element.
To find the same values at the right, just traverse the array backwards.
Here's a sample Python proof-of-concept that shows this algorithm in action. I implemented also the naïve version so we can cross-check the result from the optimized version:
from random import choice
from collections import defaultdict, deque
def make_bounds(A, fallback, arange, op):
stack = deque()
bound = [fallback] * len(A)
for i in arange:
while stack and op(A[stack[-1]], A[i]):
stack.pop()
if stack:
bound[i] = stack[-1]
stack.append(i)
return bound
def optimized_version(A):
T = zip(make_bounds(A, -1, xrange(len(A)), lambda x, y: x<=y),
make_bounds(A, len(A), reversed(xrange(len(A))), lambda x, y: x<y))
answer = defaultdict(lambda: 0)
for i, x in enumerate(A):
left, right = T[i]
answer[x] += (i-left) * (right-i)
return dict(answer)
def naive_version(A):
answer = defaultdict(lambda: 0)
for i, x in enumerate(A):
left = next((j for j in range(i-1, -1, -1) if A[j]>A[i]), -1)
right = next((j for j in range(i+1, len(A)) if A[j]>=A[i]), len(A))
answer[x] += (i-left) * (right-i)
return dict(answer)
A = [choice(xrange(32)) for i in xrange(8)]
MA1 = naive_version(A)
MA2 = optimized_version(A)
print 'Array: ', A
print 'Naive: ', MA1
print 'Optimized:', MA2
print 'OK: ', MA1 == MA2
I don't think it is possible to it directly in O(n) time: you need to iterate over all the elements of the subarrays, and you have n of them. Unless the subarrays are sorted.
You could, on the other hand, when initialising the subarrays, instead of making them normal arrays, you could build heaps, specifically min heaps when you want to find the minimum and max heaps when you want to find the maximum.
Building a heap is a linear time operation, and retrieving the maximum and minimum respectively for a max heap and min heap is a constant time operation, since those elements are found at the first place of the heap.
Heaps can be easily implemented just using a normal array.
Check this article on Wikipedia about binary heaps: https://en.wikipedia.org/wiki/Binary_heap.
I do not understand what exactly you mean by maximum of sub-arrays, so I will assume you are asking for one of the following
The subarray of maximum/minimum length or some other criteria (in which case the problem will reduce to finding max element in a 1 dimensional array)
The maximum elements of all your sub-arrays either in the context of one sub-array or in the context of the entire super-array
Problem 1 can be solved by simply iterating your super-array and storing a reference to the largest element. Or building a heap as nbro had said. Problem 2 also has a similar solution. However a linear scan is through n arrays of length m is not going to be linear. So you will have to keep your class invariants such that the maximum/minimum is known after every operation. Maybe with the help of some data structure like a heap.
Assuming you mean contiguous sub-arrays, create the array of partial sums where Yi = SUM(i=0..i)Xi, so from 1,4,2,3 create 0,1,1+4=5,1+4+2=7,1+4+2+3=10. You can create this from left to right in linear time, and the value of any contiguous subarray is one partial sum subtracted from another, so 4+2+3 = 1+4+2+3 - 1= 9.
Then scan through the partial sums from left to right, keeping track of the smallest value seen so far (including the initial zero). At each point subtract this from the current value and keep track of the highest value produced in this way. This should give you the value of the contiguous sub-array with largest sum, and you can keep index information, too, to find where this sub-array starts and ends.
To find the minimum, either change the above slightly or just reverse the sign of all the numbers and do exactly the same thing again: min(a, b) = -max(-a, -b)
I think the question you are asking is to find the Maximum of a subarry.
bleow is the code that cand do that in O(n) time.
int maxSumSubArr(vector<int> a)
{
int maxsum = *max_element(a.begin(), a.end());
if(maxsum < 0) return maxsum;
int sum = 0;
for(int i = 0; i< a.size; i++)
{
sum += a[i];
if(sum > maxsum)maxsum = sum;
if(sum < 0) sum = 0;
}
return maxsum;
}
Note: This code is not tested please add comments if found some issues.

minimum number of steps required to set all flags of array elements to 1 which were initially 0 by default [duplicate]

Two integers N<=10^5 and K<=N are given, where N is the size of array A[] and K is the length of continuous subsequence we can choose in our process.Each element A[i]<=10^9. Now suppose initially all the elements of array are unmarked. In each step we'll choose any subsequence of length K and if this subsequence has unmarked elements then we will mark all the unmarked elements which are minimum in susequence. Now how to calculate minimum number of steps to mark all the elements?
For better understanding of problem see this example--
N=5 K=3
A[]=40 30 40 30 40
Step 1- Select interval [1,3] and mark A[1] and A[3]
Step2- Select interval [0,2] and mark A[0] and A[2]
Step 3- Select interval [2,4] and mark A[4]
Hence minimum number of steps here is 3.
My approach(which is not fast enough to pass)-
I am starting from first element of array and marking all the unmarked elements equal to it at distance <=K and incrementing steps by 1.
First consider how you'd answer the question for K == N (i.e. without any effective restriction on the length of subsequences). Your answer should be that the minimum number of steps is the number of distinct values in the array.
Then consider how this changes as K decreases; all that matters is how many copies of a K-length interval you need to cover the selection set {i: A[i] == n} for each value n present in A. The naive algorithm of walking a K-length interval along A, halting at each position A[i] not yet covered for that value of n is perfectly adequate.
As we see minimum number of steps = N/k or N/k+1 and maximum number of steps =(n+k-1).
We have to optimize the total number of steps and which depend on past history of choices we made which refers to dynamic solution.
For dynamic theory tutorial see http://www.quora.com/Dynamic-Programming/How-do-I-get-better-at-DP-Are-there-some-good-resources-or-tutorials-on-it-like-the-TopCoder-tutorial-on-DP/answer/Michal-Danil%C3%A1k
Can be solved in O(n) as follows:
Trace each element a[i]. If a[i] wasn't traced before then map the number and its index and increase counter.If the number was traced previously then check whether its (last index-curr_index)>=K if yes update the index and increase count. Print count.
Map STL will be beneficial.

Find the farthest sum of two elements from zero in an array

Given an array, what is the most time- and space-efficient algorithm to find the sum of two elements farthest from zero in that array?
Edit
For example, [1, -1, 3, 6, -10] has the farthest sum equal to -11 which is equal to (-1)+(-10).
Using a tournament comparison method to find the largest and second largest elements uses the fewest comparisons, in total n+log(n)-2. Do this twice, once to find the largest and second largest elements, say Z and Y, and again to find the smallest and second smallest elements, say A and B. Then the answer is either Z+Y or -A-B, so one more comparison solves the problem. Overall, this takes 2n+2log(n)-3 comparisons. This is still O(n), but in practice is faster than scanning the entire list 4 times to find A,B,Y,Z (in total uses 4n-5 comparisons).
The tournament method is nicely explained with pictures and sample code in these two tutorials: one and two
If you mean the sum whose absolute value is maximum, it is either the largest sum or the smallest sum. The largest sum is the sum of the two maximal elements. The smallest sum is the sum of the two minimal elements.
So you need to find the four values: Maximal, second maximal, minimal, second minimal. You can do it in a single pass in O(n) time and O(1) memory. I suspect that this question might be about minimizing the constant in O(n) - you can do it by taking elements in fives, sorting each five (it can be done in 7 comparisons) and comparing the two top elements with current-max elements (3 comparisons at worst) and the two bottom elements with current-min elements (ditto.) This gives 2.6 comparisons per element which is a small improvement over the 3 comparisons per element of the obvious algorithm.
Then just sum the two max elements, sum the two min elements and take whichever value has the larger abs().
Let's look at the problem from a general perspective:
Find the largest sum of k integers in your array.
Begin by tracking the FIRST k integers - keep them sorted as you go.
Iterate over the array, testing each integer against the min value of the saved integers thus far.
If it is larger than the min value of the saved integers, replace it with the smallest value, and bubble it up to its proper sorted position.
When you've finished the array, you have your largest k integers.
Now you can easily apply this to k=2.
Just iterate over the array keeping track of the smallest and the largest elements encountered so far. This is time O(n), space O(1) and obviously you can't do better than that.
int GetAnswer(int[] arr){
int min = arr[0];
int max = arr[0];
int maxDistSum = 0;
for (int i = 1; i < arr.Length; ++i)
{
int x = arr[i];
if(Math.Abs(maxDistSum) < Math.Abs(max+x)) maxDistSum = max+x;
if(Math.Abs(maxDistSum) < Math.Abs(min+x)) maxDistSum = min+x;
if(x < min) min = x;
if(x > max) max = x;
}
return maxDistSum;
}
The key observation is that the furthest distance is either the sum of the two smallest elements or the sum of the two largest.

Resources