Give an integer array a (positive and negative numbers), how to find a continuous sub-array (can not take one, then the result is 0), so that the maximum?
For example: -2,11,-4,13,-5,-2, and the largest subkey: 11,-4,13. and for 20. What algorithm do you use to see this problem in your first response?
(1) enumeration? Yes, enumerations are omnipotent! Enumerate what? The location of the sub-array! Well enumerate an opening position I, an end position j>=i, and then seek a[i. J] The number of the and, find the biggest is OK. Okay, what's the complexity of the time?
(1.1) enumeration I,o (n)
(1.2) enumeration J,o (n)
(1.3) summation a[i. J],o (n) This is probably a calculation method:
for (int1; i <= n; i++) { for (int j = i; J <= N; j + +) { /c9>int0; for (int k = i; k <= J; k++) + = A[k] ; = max (max, sum);} }
so is O (n^3), the complexity is too high? Try it down a bit? (2) is still an enumeration! Can I calculate the and at the same time as the enumeration?
(2.1) enumeration I,o (n)
(2.2) enumerate J,o (n), here we find a[i. J] 's and not a[i. J–1] and add a[j]? So we're here when J adds 1 to add a[j] to the previous results? Right! So we effortlessly reduce complexity and get a faster algorithm with a new time complexity of O (n^2). This is probably a piece of code:
for (int1; i <= n; i++) { int0; for (int j = i; J <= N; j + +) { + = a[j] ; = max (max, sum);} }
is it to the limit? Far more than that! (3) Divide and conquer?
We cut the array from the middle, the largest sub-segments of the original array and either the largest sub-segments and (min) of the two sub-arrays, or the maximal sub-segments and (Hopewell) that span the center boundary point. So how do you calculate the maximum sub-segments across the center boundary? Still an Enumeration! From the center point to the left to find out where to get the largest, and then from the center point to the right to check where to get the largest sub-segment, add up on it. We can see that the original problem is difficult because we do not know where the sub-array starts, where it ends, there is no "focus", with the central position of the "focus", we could easily find the maximum sub-segments and by the loop linear time.
then the algorithm becomes
(3.1) Splitting the numerator array for the maximal sub-segments and sum1 of the array of approximately half the length, sum2
time complexity of T (N/2)
(3.2) to find the maximum and the maximum and sum3 time complexity O (n) from the center point to each side respectively.
so the overall time complexity is T (n) = 2 * t (N/2) + O (n) = O (Nlogn), and it's a big step, isn't it? can you optimize it? Think again, don't give up! we need a "focal point" in the solution (3) To achieve the time complexity of the sub-Problem of O (n), and in the solution (2) easily with the previous and add a new element to get the current and, then "before and" is it so important? What if the previous and the negative? It's obviously useless, isn't it? We're going to have a negative number and maybe we should start again from the current element?
think again, if I want to choose A[j], then "before and" must be the largest and is positive. Or do I change the "before and" to better, or I directly from a[j], not better?
Dynamic Planning. We record Dp[i] represents the largest and most of all the sub-segments ending in a[i]. Let's see what we just thought, I can not take a[i–1], if take a[i–1] then must be taken to a[i–1] end of the sub-paragraph and the largest one, so is dp[i–1]. What if we don't take dp[i–1]? Then I'll just take a[i] and be all alone. Note that the definition of dp[i] must be taken a[i]. Then I'll either take a[i–1] or not take a[i-1]. So that's good for dp[i]? Obviously take the biggest. So we have dp[i] = max (dp[i–1] + a[i], a[i]) in fact it and dp[i] = max (dp[i–1], 0) + A[i] is the same, meaning to say before the largest and is positive I will, otherwise I will not! What is the initial value? The initial value is dp[1] = a[1], because there is no previous choice.
So what's the result? Do we have to take the largest sub-segment and inevitably end with some a[i]? So the result is Max (Dp[i]).
In this way, our time complexity is O (n), and the spatial complexity is O (n)-because we want to record the array of DP. does the algorithm achieve optimal? It's like! can also be optimized! We notice that dp[i] = max (dp[i-1], 0) + a[i], see it is only related to dp[i–1], why should we record it all? To find the maximum value for all Dp[i]? No, the maximum value we can also ask for a comparison.
we define Endmax to represent the maximum number of sub-segments at the end of the current element and, when adding a[i], we have endmax ' = max (Endmax, 0) + a[i], and then by the way the maximum is recorded. the pseudo code is as follows; (array subscript starting from 1)
Endmax = Answer = a[1]for2 do0) + A[i] = max (answer, Endmax) endfor
The complexity of time? O (n)! Space complexity? O (1)! Simple, huh? We not only optimize the complexity of time and space, but also make the code simple and straightforward, and less prone to error.
the old-cliché question came. How do we find a sub-segment like this? See above for pseudo code Endmax = max (Endmax, 0) + a[i], for Endmax it corresponds to the end of the sub-segment is obviously a[i], how do we know the beginning of this sub-paragraph? Just see if it has been updated. That is, if endmax ' = Endmax + a[i] The corresponding child segment begins at the beginning of the preceding child segment. Otherwise, obviously Endmax start and end are a[i], let's change the Pseudo-code:
Start =1Answerstart= Asnwerend =1Endmax= Answer = a[1] forEnd =2to n Do ifEndmax >0Then Endmax+=A[end]ElseEndmax=A[end] Start=End EndIfifEndmax >answer then answer=Endmax Answerstart=Start Answerend=End Endifendfor
Here we use end as the loop variable, and whether or not the start changes by updating or not.
Summary: Through continuous optimization, we get a simple dynamic programming algorithm with TIME complexity O (n) and Space complexity O (1). Dynamic planning, it's so simple! Optimization Endless! The following:
#include <iostream>#include<cstdio>#include<cstring>using namespacestd;Long Longn,a[60000],dp,answer;intMain () {CIN>>N; for(intI=1; i<=n;i++) cin>>A[i]; DP=answer=a[1]; for(intI=2; i<=n;i++) {DP=max (DP,0LL) +A[i]; Answer=Max (dp,answer); } cout<<answer;}
If it helps you, do not forget to add praise Oh, the clatter!! See you next time! the
Basic explanation of dynamic rules four--maximum sub-segments and problems