[question]: given integer \ (a_1,a_2,a_3,..., a_n\) (may have negative numbers), the maximum value of \ (\sum_{k=i}^{j}a_k\) (for convenience, if all integers are negative, the maximum sequence and 0)
For example: input \ ( -2,11,-4,13,-5,-2\), the answer is \ (20\) (from \ (a_2\) to \ (a_4\))
Solution ①: Poor Lifting method
Outer Layer Two loops through the array to determine the upper bound of the sequence. The inner loop iterates through the sequence sum.
1 /*2 * MAXSUBSUM1: Solution ①, poor lifting method3 * Input Array a4 * Returns the maximum number of sub-sequences and5 */6 intMAXSUBSUM1 (Constvector<int> &a)7 {8 intMaxsum =0;//Store Results9 Ten for(inti =0; I < a.size (); i++) One for(intj = i; J < A.size (); J + +) A { - intThissum =0; - the for(intK = i; K <= J; k++) -Thissum + =A[k]; - - if(Thissum >maxsum) + { -Maxsum =thissum; + } A } at - returnmaxsum; -}
Obviously, the time complexity of this method is \ (O (n^3) \), and there is no practical significance, \ (n\) take a larger value when the algorithm is poor.
Solution ②: Improving the poor lifting method
The second layer each cycle by the way the sub-sequence value, and determine the result, cancel the third loop.
1 /*2 * maxSubSum2: Solution ②, improve the poor lifting method3 * Input Array a4 * Returns the maximum number of sub-sequences and5 */6 intMAXSUBSUM2 (Constvector<int> &a)7 {8 intMaxsum =0;//Store Results9 Ten for(inti =0; I < a.size (); i++) One { A intThissum =0; - - for(intj = i; J < A.size (); J + +) the { -Thissum + =A[j]; - - if(Thissum >maxsum) +Maxsum =thissum; - } + } A at returnmaxsum; -}
Obviously, the time complexity of this method is \ (O (n^2) \), on the basis of the poor lifting method is slightly improved, \ (n\) take a larger value when the algorithm effect is still poor.
Solution ③: Divide and conquer strategy
Divide the original problem into two roughly equal sub-problems, then solve them recursively. The largest sub-sequence can occur: The left half of the input data, the right half of the input data, and the middle and left half of the data span.
1 /*2 * Max3: recursive function3 * Input array A, recursive lower bound, upper bound of recursion4 * Returns the recursive maximum sub-sequence and5 */6 intMaxsumrec (Constvector<int> &a,intLeftintRight )7 {8 if(left = right)//Benchmark Situation9 {Ten if(A[left] >0)//returns a value when there is only one element (returns 0 when the element is all negative) One returnA[left]; A Else - return 0; - } the - intCenter = (left + right)/2; - intMaxleftsum =Maxsumrec (A, left, center); - intMaxrightsum = Maxsumrec (A, center +1, right); + - intMaxleftbordersum =0, Leftbordersum =0; + for(inti = center; I >= left; i--) A { atLeftbordersum + =A[i]; - if(Leftbordersum >maxleftbordersum) -Maxleftbordersum =leftbordersum; -}//the first half of the largest sub-sequence and - - intMaxrightbordersum =0, Rightbordersum =0; in for(intj = center +1; J <= Right; J + +) - { toRightbordersum + =A[j]; + if(Rightbordersum >maxrightbordersum) -Maxrightbordersum =rightbordersum; the}//the second half of the largest subsequence and * $ returnMax3 (Maxleftsum, maxrightsum, Maxleftbordersum + maxrightbordersum);//max3 A maximum function for three integersPanax Notoginseng } - the /* + * MAXSUBSUM3: Solution ③, divide and conquer strategy A * Input Array a the * Returns the maximum number of sub-sequences and + */ - intMAXSUBSUM3 (Constvector<int> &a) $ { $ returnMaxsumrec (A,0, A.size ()-1); -}
Because recursion is used and a loop is used within the recursive function, the algorithm has a time complexity of \ (O (nlog_2n) \). At this point the result is more desirable.
Solution ④: The Ultimate method
Again, we can introduce a conclusion that if \ (a[i]\) is negative, it cannot represent the starting point of the optimal sequence, because any subsequence containing \ (a[i]\) as the starting point can be improved by starting with \ (a[i+1]\). Similarly, any negative
The subsequence cannot be the prefix of the optimal subsequence. If the sub-sequence of \ (a[i]\) to \ (a[j]\) is detected as negative in the inner loop, then we can push \ (i\). The key conclusion is that we can not only push \ (i\) to \ (i+1\), but we can actually push it to \ (j+1\). In order to prove that we know from the previous conclusion that \ (a[i]\) is non-negative, followed by \ (j\) is the first subscript from subscript \ (i\) to make the sequence and negative, so that \ (p\) is \ (i+1\) to \ (j\) any subscript between, then from subscript \ (i\) to \ (j\), Sequence \ (a[i]...a[p-1]\) and always greater than sequence \ (a[p]...a[j]\) and. so pushing \ (i\) to \ (j+1\) is safe and we don't miss the optimal solution.
1 /*2 * MAXSUBSUM4: Solution ④, the Ultimate method3 * Input Array a4 * Returns the maximum number of sub-sequences and5 */6 intMAXSUBSUM4 (Constvector<int> &a)7 {8 intMaxsum =0, Thissum =0;9 Ten for(intj =0; J < A.size (); J + +) One { AThissum + =A[j]; - - if(Thissum >maxsum) theMaxsum =thissum; - Else if(Thissum <0)//key steps: Advance to j+1 (make sequence and less than 0 subscript j) -Thissum =0; - Else + Continue; - } + A returnmaxsum; at}
Obviously, the time complexity of the algorithm is \ (O (N) \), and only one scan of the data, once \ (a[i]\) is read into and processed, it does not need to be remembered, so only the constant space and linear time to run the online algorithm .
Summary: To be good at thinking about the structure of the problem, carefully study the structure of the data to find the best solution. Without thinking, you can write the most stupid method, and then gradually improve.
Reference: Data structure and algorithm analysis (c + + description). Third edition. "Mei" Mark Allen Weiss. People's post and telecommunications publishing house
Welcome to communicate correct, welcome reprint, reproduced please indicate the author and source.
Maximum sub-sequences and problems (upgrade kit)