题目:
数组中某数字减去其左边的某数字得到一个数对之差,求所有数对之差的最大值。
例如:数组{2, 4, 1, 16, 7, 5, 11, 9}中,数对之差的最大值是15(16 - 1)
分析:看到这个题目,很多人的第一反应是找到这个数组的最大值和最小值,然后觉得最大值减去最小值就是最终的结果。
但由于我们无法保证最大值一定位于数组的右边。
让每一个数字逐个减去它左边的所有数字,并通过比较得到数对之差的最大值,总的时间复杂度是O(n2)。
解法一:转化为求子数组的最大和问题
可以转化为求子数组的最大和问题。
1、有一数组array[n],数组长度为n
2、构建一个长度为n-1的辅助数组tmp[n-1],且tmp[i] = array[i] - array[i-1]; (1<=i<n),tmo[0]=0;
3、如果累加辅助数组tmp从i到j(j>i),即tmp[i] + tmp[i+1] + ... + tmp[j],
有(array[i] - array[i-1]) + (array[i+1] -array[i]) + ... + (array[j] - array[j-1]) = array[j] - array[i-1]
分析至此,发现数组中最大的数对之差(即array[j] - array[i-1])其实是辅助数组tmp中最大的连续子数组之和。
如何求连续子数组最大之和,
即为 sum[i+1] = max( sum[i]+tmp[i+1] , tmp[i+1] , sum[i] ); 其中sum[i]表示tmp数组0~i的最大连续子数组和。
可分为两种情况:如果sum[i]包含tmp[i],则sum[i+1]是 sum[i]与sum[i]+tmp[i+1]的较大者;
如果sum[i]不包含tmp[i],则sum[i+1]是 sum[i]与tmp[i+1]的较大者。
可以简化为:如果sum[i]>0 ,则 sum[i+1]=sum[i]+tmp[i+1];(这里比较sum[i]+tmp[i+1] 和 tmp[i+1])
否则sum[i+1]=tmp[i+1];
再将sum[i+1]与sum[i]比较。
同时可以将数组sum[i]用一个变量表示。
具体实现:
class Solution { public: int maxProfit(vector<int> &prices) { // Start typing your C/C++ solution below // DO NOT write int main() function if(prices.size()<=0) return 0; vector<int> tmpvec(prices.size()); tmpvec[0]=0; for(int i=1; i<prices.size() ; i++) tmpvec[i] = prices[i]-prices[i-1]; int max=0; int t=0; for(int j=0;j<tmpvec.size();j++) { if(t>0) t = t+tmpvec[j]; else t = tmpvec[j]; if(t>max) max = t; } return max; } };
解法二:动态规划
对于数组array[i],我们只需求的 array[i] 与 前面 0~i-1 之间的最小值做差,求的最大的差。
即 tmp[i] = array[i] - min(array[0~i-1])
所以我们遍历时,需要时刻更新当前的min,以及最大差。
class Solution {
public:
int maxProfit(vector<int> &prices) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(prices.size()<=1)
return 0;
int i=0, j=1;
int minda = prices[0];
int max = prices[j]-minda;
for(j=1;j<prices.size();j++)
{
if(prices[j]<minda)
minda = prices[j];
if(prices[j]-minda>max)
max = prices[j]-minda;
}
return max;
}
};
其中 minda 表示 当前最小元素,max 表示最大差。
实现三:
class Solution {
public:
int maxProfit(vector<int> &prices) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(prices.size()<=1)
return 0;
int minda = prices[0];
int max = 0;
for(int j=1;j<prices.size();j++)
{
if(prices[j]-minda>max)
max = prices[j]-minda;
if(prices[j]<minda)
minda = prices[j];
}
return max;
}
};