标签:
寻找数组A的和最大的非空连续子数组。例如:int A[] = {1, -2, 3, 10, -4, 7, 2, -5}的最大子数组为3, 10, -4, 7, 2,其最大和为18。
方法1:枚举所有子数组并求出他们的和。
长度为n的数组有O(n2)个子数组(即:n + n-1 + ... + 1=n(n+1)/2);而且求一个长度为n的数组的和的时间复杂度为O(n)。因此这种思路的时间复杂度是O(n3)。
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 int main(void) 6 { 7 vector<int> vtr; 8 vector<int>::size_type i, j, k; 9 int tmp, maxSum, lpos, rpos; 10 11 while (cin >> tmp) 12 { 13 vtr.push_back(tmp); 14 } 15 16 for (i = 0; i != vtr.size(); i++) 17 { 18 cout << vtr[i] << " "; 19 } 20 cout << endl; 21 22 maxSum = vtr[0]; 23 lpos = 0; 24 rpos = 0; 25 for (i = 0; i != vtr.size(); i++) 26 { 27 for (j = i + 1; j != vtr.size(); j++) 28 { 29 tmp = 0; 30 for (k = i; k <= j; k++) 31 { 32 tmp += vtr[k]; 33 } 34 35 if (tmp > maxSum) 36 { 37 maxSum = tmp; 38 lpos = i; 39 rpos = j; 40 } 41 } 42 } 43 44 cout << "maxSum = " << maxSum << endl 45 << "Lpos = " << lpos << endl 46 << "Rpos = " << rpos << endl; 47 48 return 0; 49 }
方法2:当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。
#include <iostream> #include <vector> using namespace std; int FindMaxSubArray(vector<int> &vec, int &lpos, int &rpos) { if (vec.size() == 0) { return INT_MIN; } int maxSum = 0, curSum = 0; for (vector<int>::size_type i = 0; i != vec.size(); i++) { curSum += vec[i]; if (curSum < 0) { curSum = 0; lpos = i + 1; } if (curSum > maxSum) { maxSum = curSum; rpos = i; } } if (maxSum == 0) //数组元素全为非正,最大子数组长度为1 { maxSum = vec[0]; lpos = 0; rpos = 0; for (vector<int>::size_type i = 1; i != vec.size(); i++) { if (vec[i] > maxSum) { maxSum = vec[i]; lpos = i; rpos = i; } } } return maxSum; } int main(void) { vector<int> vec; int tmp, lpos, rpos, maxSum; while (cin >> tmp) { vec.push_back(tmp); } maxSum = FindMaxSubArray(vec, lpos, rpos); cout << "maxSum = " << maxSum << endl << "Lpos = " << lpos << endl << "Rpos = " << rpos << endl; return 0; }
方法3:分治策略。
假定我们要寻找子数组A[low..high]的最大子数组,使用分治法意味着我们要将子数组划分为两个规模尽可能相等的子数组。也就是说,找到子数组的中央位置,比如mid,然后求解两个子数组A[low..mid]和A[mid + 1..high]。所以,A[low..high]的任何连续子数组A[i..j]所处的位置必然是三种情况之一:
(1)完全位于子数组A[low..mid]中,因此low<=i<=j<=mid;
(2)完全位于子数组A[mid + 1..high]中,因此mid<=i<=j<=high;
(3)跨越了中点,因此low<=i<=mid<j<=high;
A[low..high]的一个最大子数组必然是完全位于A[low..mid]中、完全位于A[mid + 1..high]中或者跨越中点的所有子数组中和最大者。
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 bool FindMaxCrossingSubArray(const vector<int> &vec, int &low, int mid, int &high, int &crossSum) 6 { 7 if (vec.size() == 0) 8 { 9 return false; 10 } 11 12 int leftSum = INT_MIN, rightSum = INT_MIN; 13 int sum = 0, maxLow, maxHight; 14 int i; 15 16 for (i = mid; i >= low; i--) 17 { 18 sum += vec[i]; 19 if (sum > leftSum) 20 { 21 leftSum = sum; 22 maxLow = i; 23 } 24 } 25 26 sum = 0; 27 for (i = mid + 1; i <= high; i++) 28 { 29 sum += vec[i]; 30 if (sum > rightSum) 31 { 32 rightSum = sum; 33 maxHight = i; 34 } 35 } 36 37 low = maxLow; 38 high = maxHight; 39 crossSum = leftSum + rightSum; 40 41 return true; 42 } 43 44 bool FindMaximumSubArray(const vector<int> vec, int &low, int &high, int &maxSum) 45 { 46 if (vec.size() == 0) 47 { 48 return false; 49 } 50 51 int leftLow, leftHigh; 52 int rightLow, rightHigh; 53 int leftSum, rightSum, crossSum; 54 int midLow, midHigh; 55 int tmid; 56 vector<int>::size_type i; 57 58 if (low == high) 59 { 60 i = low; 61 maxSum = vec[i]; 62 return true; 63 } 64 else 65 { 66 tmid = (low + high) / 2; 67 68 leftLow = low; 69 leftHigh = tmid; 70 FindMaximumSubArray(vec, leftLow, leftHigh, leftSum); 71 72 midLow = low; 73 midHigh = high; 74 FindMaxCrossingSubArray(vec, midLow, tmid, midHigh, crossSum); 75 76 rightLow = tmid + 1; 77 rightHigh = high; 78 FindMaximumSubArray(vec, rightLow, rightHigh, rightSum); 79 80 if (leftSum >= rightSum && leftSum >= crossSum) 81 { 82 low = leftLow; 83 high = leftHigh; 84 maxSum = leftSum; 85 return true; 86 } 87 else if (rightSum >= leftSum && rightSum >= crossSum) 88 { 89 low = rightLow; 90 high = rightHigh; 91 maxSum = rightSum; 92 return true; 93 } 94 else 95 { 96 low = midLow; 97 high = midHigh; 98 maxSum = crossSum; 99 return true; 100 } 101 } 102 } 103 104 int main(void) 105 { 106 vector<int> vec; 107 int tmp, maxSum, low, high; 108 109 while (cin >> tmp) 110 { 111 vec.push_back(tmp); 112 } 113 114 low = 0; 115 high = vec.size() - 1; 116 FindMaximumSubArray(vec, low, high, maxSum); 117 118 cout << "Low = " << low << endl 119 << "High = " << high << endl 120 << "maxSum = " << maxSum << endl; 121 122 return 0; 123 }
标签:
原文地址:http://www.cnblogs.com/mengwang024/p/4202419.html