如下圖所示,Divide and Conquer 的基本概念是,將數列分成兩塊,各自回報最大的值,如藍色部分;然而這是最大子序列不只會出現在左邊或右邊,也有可能出現橫跨兩邊的紅色區域,所以還要再找出紅色區域的最大值。由於紅色區域表示的是橫跨兩邊,所以只要考慮包含中點的情況,如圖紅色元素與綠色區域,最後最大子序列的值即為紅色區域或藍色區域的最大值。
using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespaceMaximumSubsequence { // O(n^3) classBruteForce { publicstaticintGetMax(int[] array) { int max = array[0], sum; for (int start = 0; start < array.Length; ++start) for (int end = 0; end < array.Length; ++end) { sum = 0; for (int i = start; i <= end; ++i) sum += array[i]; max = Math.Max(max, sum); } return max; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespaceMaximumSubsequence { // O(n), Kadane's 演算法 (dynamic porgramming), 可不取版本 classKadanes { publicstaticintGetMax(int[] array) { int sum = 0; int max = array[0]; for (int i = 0; i < array.Length; ++i) { sum += array[i]; sum = Math.Max(0, sum); max = Math.Max(sum, max); } return max; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespaceMaximumSubsequence { // O(n), Kadane's 演算法 (dynamic porgramming), 至少取一個版本 classKadanesOne { publicstaticintGetMax(int[] array) { int sum = Detect(array); if (sum < 0) return sum; int max = array[0]; for (int i = 0; i < array.Length; ++i) { sum += array[i]; sum = Math.Max(0, sum); max = Math.Max(sum, max); } return max; }
// 測試是否全為負數,是的話回傳最大的負數,否則回傳 0 privatestaticintDetect(int[] array) { int max = array[0]; for (int i = 0; i < array.Length; ++i) { if (array[i] >= 0) return0; max = Math.Max(array[i], max); } return max; } } }
Java
暴力法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// O(n^3) publicclassBruteForce { publicstaticintGetMax(int[] array) { intmax= array[0], sum; for (intstart=0; start < array.length; ++start) for (intend=0; end < array.length; ++end) { sum = 0; for (inti= start; i <= end; ++i) sum += array[i]; max = Math.max(max, sum); } return max; } }
改良式暴力法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// O(n^2) publicclassRefineBruteForce { publicstaticintGetMax(int[] array) { intmax= array[0], sum; for (intstart=0; start < array.length; ++start) { sum = 0; for (inti= start; i < array.length; ++i) { sum += array[i]; max = Math.max(max, sum); } } return max; } }
classBruteForce { public: staticintGetMax(int* array, int length); protected: private: };
#endif// BRUTEFORCE_H
BruteForce.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include"BruteForce.h"
intBruteForce::GetMax(int* array, int length) { int max_sum = array[0], sum; for (int start = 0; start < length; ++start) for (int end = 0; end < length; ++end) { sum = 0; for (int i = start; i <= end; ++i) sum += array[i]; max_sum = max(max_sum, sum); } return max_sum; }
classDivideAndConquer { public: staticintGetMax(int* array, int length); staticintGetMax(int* array, int length, int start, int end); staticintGetCrossMax(int* array, int length, int start, int middle, int end); protected: private: };
classKadanes { public: staticintGetMax(int* array, int length); protected: private: };
#endif// KADANES_H
KadanesOne.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include"Kadanes.h"
// O(n), Kadane's 演算法 (dynamic porgramming), 可不取版本 intKadanes::GetMax(int* array, int length) { int sum = 0; int max_sum = array[0]; for (int i = 0; i < length; ++i) { sum += array[i]; sum = max(0, sum); max_sum = max(sum, max_sum); } return max_sum; }