1124. 表现良好的最长时间段
题目链接:1124. 表现良好的最长时间段
方法:前缀和 + 单调栈
前缀和简介
对于数组
s[0] = 0;
for (int i = 1; i <= n; i ++ ) {
s[i] = s[i - 1] + a[i - 1];
}
当前缀和数组
解题思路
- 原问题:表现良好时间段—
时间段内,劳累的天数 不劳累的天数,且要求 越长越好。 - 由于涉及区间内计数,考虑前缀和算法,可以在
时间内获取任一区间内的和。在此问题中,存在两种状态,设劳累的一天为 , 不劳累的一天为 ,计算 数组的前缀和数组 (为了处理边界,前缀和从 开始计算,默认 )。 - 问题转化:表现良好时间段—
时间段内, ,区间长度为 。此时问题可以转化为,在 数组中,找 ,且 ,并且 尽可能的大。 - 单调栈:初始化栈
,对于区间的左端点 选取,若 ,不需要入栈,因为一旦有右端点 ,那么 ,此时选栈顶坐标作为左端点更远;否则左端点 入栈。
当全部可能的左端点入栈后,为了确保 相差最大,从 枚举右端点 ,若 ,则 为良好时间段,取 ,并 出栈,继续比较下一个栈顶,当前右端点若不满足条件 ,则枚举下一个右端点。
代码
class Solution {
public:
int longestWPI(vector<int>& hours) {
int n = hours.size(), cnt[n + 1], ans = 0; // cnt[i],表示前i天, 劳累的天数 - 不劳累的天数
stack<int> stk;
stk.push(0); cnt[0] = 0;
for (int i = 1; i <= n; i ++ ) {
cnt[i] = cnt[i - 1] + (hours[i - 1] > 8 ? 1 : -1);
if (cnt[i] < cnt[stk.top()]) stk.push(i);
}
for (int i = n; i > 0; i -- ) {
while (!stk.empty() && cnt[i] > cnt[stk.top()]) {
ans = max(ans, i - stk.top());
stk.pop();
}
}
return ans;
}
};
复杂度分析
时间复杂度:
空间复杂度:
相关题目
分类:
leetcode题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具