见上一篇: 较难算法美丽塔时间复杂度O(n)-CSDN博客
单调栈分类、封装和总结
https://blog.csdn.net/he_zhidan/article/details/135150163
O(n)
接着上篇。从左向右依次处理Left,处理Left[i]时,从右向左寻找第一个符合maxHeights[j]
可以用栈实现,入栈maxHeights[i]之前,先出栈大于等于maxHeights[i]的数,剩余的都小于maxHeights[i]的数。也就是栈按升序排序的。由于maxHeights[i]和heights[i]都可以通过索引查询,栈中只需要记录索引。
Right类似,不再累赘。
| maxHeights | Left的栈情况 |
| {1,2,3,4,5} | 1 12 123 1234 12345 |
| {5,4,3,2,1} | 5 4 3 2 1 |
| {1,2,4,3,5} | 1 12 124 123 1235 |
| {3,1,2} | 3 1 12 |
| {2,1,3} | 2 1 13 |
- class Solution {
- public:
- long long maximumSumOfHeights(vector<int>& maxHeights) {
- m_c = maxHeights.size();
- m_vLeft.resize(m_c);
- m_vRight.resize(m_c);
- {//处理左边
- stack<int> sta;//记录做边的索引
- for (int i = 0; i < m_c; i++)
- {
- const auto& h = maxHeights[i];
- while (sta.size() && (maxHeights[sta.top()] >= h))
- {
- sta.pop();//左边比右边大,不会被选中
- }
- if (sta.size())
- {
- m_vLeft[i] = m_vLeft[sta.top()] + (long long)h * (i - sta.top());
- }
- else
- {
- m_vLeft[i] = (long long)h * (i -(-1) );
- }
- sta.emplace(i);
- }
- }
-
- {//处理右边
- stack<int> sta;//记录做边的索引
- for (int i = m_c - 1; i >= 0; i--)
- {
- const auto& h = maxHeights[i];
- while (sta.size() && (maxHeights[sta.top()] >= h))
- {
- sta.pop();//左边比右边大,不会被选中
- }
- if (sta.size())
- {
- m_vRight[i] = m_vRight[sta.top()] + (long long)h * (sta.top()-i);
- }
- else
- {
- m_vRight[i] = (long long)h * (m_c-i);
- }
- sta.emplace(i);
- }
- }
-
- long long llRet = 0;
- for (int i = 0; i < m_c; i++)
- {//假定i是山顶
- long long llCur = m_vLeft[i] + m_vRight[i] - maxHeights[i];
- llRet = max(llRet, llCur);
- }
- return llRet;
- }
- int m_c;
- vector<long long> m_vLeft, m_vRight;
- };
class CDebug : public Solution
{
public:
long long maximumSumOfHeights(vector
{
vector
long long llRet = Solution::maximumSumOfHeights(maxs);
for (int i = 0 ; i < vLeft.size();i++ )
{
assert(m_vLeft[i] == vLeft[i]);
assert(m_vRight[i] == vRight[i]);
}
//调试用代码
std::cout << "Left: ";
for (int i = 0; i < m_c; i++)
{
std::cout << m_vLeft[i] << " ";
}
std::cout << std::endl;
std::cout << "Right: ";
for (int i = 0; i < m_c; i++)
{
std::cout << m_vRight[i] << " ";
}
std::cout << std::endl;
return llRet;
}
};
int main()
{
vector < vector
{{5,4,3,2,1},{5,8,9,8,5},{15,10,6,3,1}} ,
{{1,2,4,3,5},{1,3,7,9,14},{5,8,10,6,5}},
{{3,1,2}, {3,2,4},{5,2,2}},
{{2,1,3},{2,2,5},{4,2,3}},
{{1000000000,1000000000,1000000000},{1000000000,2000000000,3000000000LL},{3000000000LL,2000000000,1000000000}} };
for (auto& vv : param)
{
auto res = CDebug().maximumSumOfHeights(vv[0], vv[1], vv[2]);
}
//auto res = Solution().maxPalindromes("rire", 3);
//CConsole::Out(res);
}
- class CRangIndex
- {
- public:
- template<class _Pr>
- CRangIndex(int iVectorSize, _Pr CurIndexCmpStackTopIndex)
- {
- m_c = iVectorSize;
- m_vLeft.assign(m_c, -1);
- m_vRight.assign(m_c, m_c);
- stack<int> sta;
- for (int i = 0; i < m_c; i++)
- {
- while (sta.size() && (CurIndexCmpStackTopIndex(i, sta.top())))
- {
- m_vRight[sta.top()] = i;
- sta.pop();
- }
- if (sta.size())
- {
- m_vLeft[i] = sta.top();
- }
- sta.emplace(i);
- }
- }
-
- template<class _Pr>
- CRangIndex(const vector<int>& nums, _Pr CurValueCmpStackTopValue)
- {
- m_c = nums.size();
- m_vLeft.assign(m_c, -1);
- m_vRight.assign(m_c, m_c);
- stack<int> sta;
- for (int i = 0; i < m_c; i++)
- {
- while (sta.size() && (CurValueCmpStackTopValue(nums[i], nums[sta.top()])))
- {
- m_vRight[sta.top()] = i;
- sta.pop();
- }
- if (sta.size())
- {
- m_vLeft[i] = sta.top();
- }
- sta.emplace(i);
- }
- }
- int m_c;
- vector<int> m_vLeft, m_vRight;//vLeft[i] 从右向左第一个小于nums[i] ;vRight[i] 是第一个小于等于nums[i]。
- };
-
- class Solution {
- public:
- long long maximumSumOfHeights(vector<int>& maxHeights) {
- CRangIndex ri(maxHeights, std::less<>());
- m_vLeft.resize(ri.m_c);
- for (int i = 0; i < ri.m_c; i++)
- {
- m_vLeft[i] = (-1 == ri.m_vLeft[i]) ? 0 : m_vLeft[ri.m_vLeft[i]];
- m_vLeft[i] += ((long long)i - ri.m_vLeft[i]) * maxHeights[i];
- }
- m_vRight.resize(ri.m_c);
- long long llRet = 0;
- for (int i = ri.m_c - 1; i >= 0; i--)
- {
- m_vRight[i] = (ri.m_c == ri.m_vRight[i]) ? 0 : m_vRight[ri.m_vRight[i]];
- m_vRight[i] += ((long long)ri.m_vRight[i] - i ) * maxHeights[i];
- long long llCur = m_vLeft[i] + m_vRight[i] - maxHeights[i];
- llRet = max(llRet, llCur);
- }
- return llRet;
- }
- int m_c;
- vector<long long> m_vLeft, m_vRight;
- };

如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。
https://edu.csdn.net/course/detail/38771
我的其它课程
https://edu.csdn.net/lecturer/6176
win7 VS2019 C++17 或Win10 VS2022 Ck++17
算法精讲《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
| 作者人生格言 |
| 有所得,以墨记之,故曰墨家 |
| 闻缺陷则喜。问题发现得越早,越给老板省钱。 |
| 算法是程序的灵魂 |
![]()