今日头条编程题第二道
解答
解法一:暴力解法
穷举所有数组中所有子数组,并计算所有子数组中最小值*子数组所有数的和,求出其中的最大值即可,代码如下:
int enum_method(vector<int> &num) {
int n = num.size();
int maxSum = INT_MIN;
vector<int> tmp;
for (int i = 0; i<n; ++i) {
for (int j = i; j<n; ++j) {
tmp.clear();
for (int k = i; k <= j; ++k) {
tmp.push_back(num[k]);
}
sort(tmp.begin(), tmp.end());
int curSum = tmp[0] * vecSum(tmp, 0, tmp.size() - 1);
maxSum = max(curSum, maxSum);
}
}
return maxSum;
}
时间复杂度为O(N*N*N)
解法二:单调栈解法
基本思想:
1. 以数组中每一个值为最小值,假设这个最小值为num[k], 分别找到以该值num[k]为最小值,数组最左边的小于该值的下标i,和数组最右边的小于该值的下标j, 则区间num[i+1,j-1]为以num[k]为最小值所能达到的最大区间,则此区间能达到的最大值为num[k]*Sum(i+1,j-1),其中Sum函数为数组中区间[i+1,j+1]的所有数的和
2. 按照步骤1(可利用单调栈实现)结算数组中每一个值,维护一个最大值maxSum, 当遍历数组的最后一个数,所得maxSum即为所求。
举例说明步骤1单调栈的实现:
如现在有一个数组vector<int> num=[6,2,5,5,5,4,7], 接着我们创建一个栈stack<int> s
,我们将数组的数压栈入栈的规则如下:
- 如果s为空,或者当前遍历元素num[i]的值大于等于栈顶元素,那么我们直接将num[i]的下标i压入栈中。
- 如果s不为空,且当前遍历元素num[i]的值小于等于栈顶元素,那么我们就依次从栈中弹出元素,直到num[i]的值大于栈顶元素。并在弹出的过程中结算弹出中每一个数所构成的区间的区间中最小数*区间所有数和的最大值。
- 如果数组中的元素已经全部遍历压栈,如果此时栈不为空,我们就重复步骤2,将栈中的元素全部结算。
如现在我们开始遍历数组[6,2,5,5,5,4,7],
- 遍历到6时,因为此时栈为空,我们直接将6的下标0压入栈中。此时栈中元素为{0}
- 遍历到2时,此时栈不为空,且num[i]=2<6(栈顶元素),根据规则2,则将6的下标0出栈保存到top,并结算以6为最小值的最大区间的最大值。即我们知道6最左边小于6的元素的下标是不存在,那么我