力扣单调栈算法专题训练
2023-12-23 06:12:55
1 专题说明
本博客用来计算力扣上的单调栈题目、解题思路和代码。
2 训练
题目1:2866美丽塔II。
解题思路:先计算出prefix[i],表示0~i
满足递增情况下,0~i
上的元素之和最大值。然后计算出suffix[i],表示i~n-1
满足递增情况下,i~n-1
上的元素之和最大值。那么以i
为峰顶的美丽塔的元素之和的最大值为prefix[i] + suffix[i] - nums[i]
,遍历i,获得答案即可。
本质上,还是可以归类为:找到i左边,并且<=nums[i]的元素值。
C++代码如下,
class Solution {
public:
long long maximumSumOfHeights(vector<int>& maxHeights) {
int n = maxHeights.size();
vector<long long> prefix(n, 0); //prefix[i]表示0~i是递增的情况下,0~i的元素之和
stack<int> stk;
for (int i = 0; i < n; ++i) {
while (!stk.empty() && maxHeights[stk.top()] > maxHeights[i]) {
stk.pop();
}
if (stk.empty()) {
prefix[i] = (long long)(i + 1) * maxHeights[i];
} else {
prefix[i] = prefix[stk.top()] + (long long)(i - stk.top()) * maxHeights[i];
}
stk.push(i);
}
while (!stk.empty()) {
stk.pop();
}
vector<long long> suffix(n, 0); //suffix[i]表示i~n-1是递减的情况下,i~n-1的元素之和
for (int i = n - 1; i >= 0; --i) {
while (!stk.empty() && maxHeights[stk.top()] > maxHeights[i]) {
stk.pop();
}
if (stk.empty()) {
suffix[i] = (long long)(n - i) * maxHeights[i];
} else {
suffix[i] = suffix[stk.top()] + (long long)(stk.top() - i) * maxHeights[i];
}
stk.push(i);
}
long long res = 0;
for (int i = 0; i < n; ++i) {
res = max(res, prefix[i] + suffix[i] - maxHeights[i]);
}
return res;
}
};
python3代码如下,
class Solution:
def maximumSumOfHeights(self, maxHeights: List[int]) -> int:
n = len(maxHeights)
prefix = [0 for i in range(n)] #0~i的递增数组的和的最大值
stk = []
for i in range(n):
while len(stk) and maxHeights[stk[-1]] > maxHeights[i]:
del stk[-1]
if len(stk) == 0:
prefix[i] = (i + 1) * maxHeights[i]
else:
prefix[i] = prefix[stk[-1]] + (i - stk[-1]) * maxHeights[i]
stk.append(i)
stk.clear()
suffix = [0 for i in range(n)] #i~n-1的递减数组的和的最大值
for i in range(n-1,-1,-1):
while len(stk) and maxHeights[stk[-1]] > maxHeights[i]:
del stk[-1]
if len(stk) == 0:
suffix[i] = (n - i) * maxHeights[i]
else:
suffix[i] = suffix[stk[-1]] + (stk[-1] - i) * maxHeights[i]
stk.append(i)
res = 0
for i in range(n):
#print(f"i = {i}, prefix[i] = {prefix[i]}, suffix[i] = {suffix[i]}.")
res = max(res, prefix[i] + suffix[i] - maxHeights[i])
return res
题目2:496下一个更大元素I。
解题思路:直接找右边首次大于它的元素即可。
C++代码如下,
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int,int> mp; //mp[x]表示nums2中元素x的右边,第一个比它大的元素
stack<int> stk;
for (int i = nums2.size() - 1; i >= 0; --i) {
while (!stk.empty() && stk.top() <= nums2[i]) {
stk.pop();
}
if (!stk.empty()) {
mp[nums2[i]] = stk.top();
} else {
mp[nums2[i]] = -1;
}
stk.push(nums2[i]);
}
vector<int> res;
for (auto x : nums1) {
res.emplace_back(mp[x]);
}
return res;
}
};
python3代码如下,
class Solution:
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
n = len(nums2)
mp = collections.defaultdict(int)
stk = []
for i in range(n - 1, -1, -1):
while len(stk) and stk[-1] <= nums2[i]:
del stk[-1]
if len(stk):
mp[nums2[i]] = stk[-1]
else:
mp[nums2[i]] = -1
stk.append(nums2[i])
res = []
for x in nums1:
res.append(mp[x])
return res
题目3:503下一个更大元素II。
解题思路:环形问题,扩展两倍原数组即可,接下来就是找右侧首次大于它的元素。
C++代码如下,
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
vector<int> a(2 * n, 0);
for (int i = 0; i < n; ++i) {
a[i] = a[i + n] = nums[i];
}
vector<int> ans(2 * n, -1);
stack<int> stk;
for (int i = 2 * n - 1; i >= 0; --i) {
while (!stk.empty() && stk.top() <= a[i]) {
stk.pop();
}
if (!stk.empty()) {
ans[i] = stk.top();
}
stk.push(a[i]);
}
vector<int> res(n, -1);
for (int i = 0; i < n; ++i) {
res[i] = ans[i];
}
return res;
}
};
python3代码如下,
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
n = len(nums)
a = [-1 for i in range(2 * n)]
for i in range(n):
a[i] = a[i + n] = nums[i]
ans = [-1 for i in range(2 * n)]
stk = []
for i in range(2 * n - 1, -1, -1):
while len(stk) and stk[-1] <= a[i]:
del stk[-1]
if len(stk):
ans[i] = stk[-1]
stk.append(a[i])
res = [-1 for i in range(n)]
for i in range(n):
res[i] = ans[i]
return res
题目4:
文章来源:https://blog.csdn.net/YMWM_/article/details/135161702
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!