持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【LeetCode 2100. 适合打劫银行的日子 】- JavaScript(前缀和+后缀和)
题目描述
你和一群强盗准备打劫银行。给你一个下标从 0 开始的整数数组 security ,其中 security[i] 是第 i 天执勤警卫的数量。日子从 0 开始编号。同时给你一个整数 time 。
如果第 i 天满足以下所有条件,我们称它为一个适合打劫银行的日子:
第 i 天前和后都分别至少有 time 天。
第 i 天前连续 time 天警卫数目都是非递增的。
第 i 天后连续 time 天警卫数目都是非递减的。
更正式的,第 i 天是一个合适打劫银行的日子当且仅当:security[i - time] >= security[i - time + 1] >= ... >= security[i] <= ... <= security[i + time - 1] <= security[i + time].
请你返回一个数组,包含 所有 适合打劫银行的日子(下标从 0 开始)。返回的日子可以 任意 顺序排列。
示例 1:
输入:security = [5,3,3,3,5,6,2], time = 2 输出:[2,3] 解释: 第 2 天,我们有 security[0] >= security[1] >= security[2] <= security[3] <= security[4] 。 第 3 天,我们有 security[1] >= security[2] >= security[3] <= security[4] <= security[5] 。 没有其他日子符合这个条件,所以日子 2 和 3 是适合打劫银行的日子。
前后缀和
思路分析:
前缀和:分别用两个数组a,b分别记录数组中元素递减、递增的累加和,通过[i]-[i-time]判断该区间递减的个数、递增的个数。后缀和反之同理。
前后缀和思路:从左到右,从右到左,各扫描一次。分别用 left 和 right 记录扫描的结果。left 的结果就是当前位置i 左边有几个连续的非递增数字。right 的结果就是当前位置i 右边有几个连续的非递增数字。(非递增的状态转移)。实现步骤:
- 初始化第i天满足条件的集合
- 左右两个边界,左边界表示开始下降的边界,右边界表示结束上升的边界
- 遍历天数,遍历到第i天,第i天人数大于i-1天,左边界变成当前索引
- 右边界必须大于等于当前索引位置,和上次的right
- 如果后面的元素比当前元素大,则向右移动右边界
- 左右两边距离取较小值,如果超过 time,就添加到结果数组
var goodDaysToRobBank = function(security, time) {
let res = []
let len = security.length
let pre = new Array(len).fill(0),post = new Array(len).fill(0)
for(let i = 1; i < len; i++) {
if(security[i - 1] >= security[i]) {
pre[i] = pre[i - 1] + 1
}
}
for(let i = len - 2; i >= 0; i--) {
if(security[i] <= security[i + 1]) {
post[i] = post[i + 1] + 1
}
}
for(let i = 0; i < len; i++) {
if( pre[i] >=time && post[i] >= time ) res.push(i)
}
console.log(pre, post)
return res
};
注意:这道题目我刚开始想了半天非递增的可能性,也就是是i这天要满足前time天递减,后time天递增。发现自己想多了~
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤