这道题的本质是求连续最大子区间问题,将数组中的每个元素转换为与前一位的差,那么最大的子区间就是收益最高的区间。
在求最大子区间时,可以想到,如果将区间分为两部分,那么最大子区间可能是左边区间的子区间,右边区间的子区间,也可能跨越中点的区间。对于左右子区间,可以很容易转化为递归步,所以只需要计算跨越中点的最大区间,这个很简单:从中点开始往左往右加,若更大,则更新区间端点,否则继续加。
1 intfind_max_subarray(vector<int>& a, int low, int high) 2 3 { 4 5 if (low == high) 6 7 { if(a[low] < 0) 8 9 return 0; 10 11 else 12 13 return a[low];} 14 15 else 16 17 { 18 19 int mid = (low + high) / 2; 20 21 int left_max = find_max_subarray(a, low,mid); 22 23 int right_max = find_max_subarray(a,mid+1, high); 24 25 int sum = 0, left = mid, t1 = a[mid]; 26 27 for (int i = left; i >= low; i--) 28 29 { 30 31 sum += a[i]; 32 33 if (sum > t1) 34 35 { 36 37 t1 = sum; 38 39 left = i; 40 41 } 42 43 } 44 45 int right = mid + 1, t2 = a[right]; 46 47 sum = 0; 48 49 for (int i = right; i <= high; i++) 50 51 { 52 53 sum += a[i]; 54 55 if (sum > t2) 56 57 { 58 59 t2 = sum; 60 61 right= i; 62 63 } 64 65 } 66 67 int cross_max = t1 + t2; 68 69 if (left_max < 0 && right_max< 0 && cross_max < 0) 70 71 return 0; 72 73 if (left_max >=cross_max&&left_max >= right_max) 74 75 return left_max; 76 77 else if (right_max >= cross_max) 78 79 return right_max; 80 81 else 82 83 return cross_max; 84 85 } 86 87 88 89 90 91 } 92 93 classSolution { 94 95 public: 96 97 int maxProfit(vector<int>&prices) { 98 99 int n = prices.size(); 100 101 if (n<2) 102 103 return 0; 104 105 for (int i = n - 1; i > 0; --i) 106 107 prices[i] -= prices[i - 1]; 108 109 return find_max_subarray(prices, 1, n - 1); 110 111 } 112 113 };