这道题的本质是求连续最大子区间问题,将数组中的每个元素转换为与前一位的差,那么最大的子区间就是收益最高的区间。
在求最大子区间时,可以想到,如果将区间分为两部分,那么最大子区间可能是左边区间的子区间,右边区间的子区间,也可能跨越中点的区间。对于左右子区间,可以很容易转化为递归步,所以只需要计算跨越中点的最大区间,这个很简单:从中点开始往左往右加,若更大,则更新区间端点,否则继续加。
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 };