【LetMeFly】2100. A good day to rob a bank
Now it seems that the topic
2100. 适合野炊的日子
has been .
Leetcode question link: https://leetcode.cn/problems/find-good-days-to-rob-the-bank/
You and a group of robbers are going to rob a bank. You are given an array of integers whose index starts from 0security
, where security[i]
is i
the number of guards on duty on the day. Days 0
are numbered from the beginning. Also gives you an integer time
.
If i
day satisfies all of the following conditions, we call it a suitable day to rob a bank:
i
There are at least one day before and after the first daytime
.i
The number of guards on consecutive days before the first daytime
is non-increasing.- The number of guards is non-decreasing on
i
consecutive days after the first day.time
More formally, day i
is a suitable day to rob a bank if and only if: security[i - time] >= security[i - time + 1] >= ... >= security[i] <= ... <= security[i + time - 1] <= security[i + time]
.
Please return an array containing all days suitable for bank robbery (the subscript starts from 0 ). The days returned can be in any order.
Example 1:
Input: security = [5,3,3,3,5,6,2], time = 2 Output: [2,3] Explanation: On day 2, we have security[0] >= security[1] >= security[2] <= security[3] <= security[4] . On day 3, we have security[1] >= security[2] >= security[3] <= security[4] <= security[5] . No other days fit this criteria, so days 2 and 3 are good days for bank robberies.
Example 2:
Input: security = [1,1,1,1,1], time = 0 Output: [0,1,2,3,4] Explanation: Because time is equal to 0, every day is a suitable day to rob a bank. So return every day.
Example 3:
Input: security = [1,2,3,4,5,6], time = 2 Output: [] Explanation: There is no non-increasing number of guards in the first 2 days of any day. So there are no days suitable for bank robbery, and an empty array is returned.
hint:
1 <= security.length <= 105
0 <= security[i], time <= 105
Ideas
Method 1: Classification discussion
<small time complexity O ( n ) O(n)O ( n ) , space complexity O (1), difficulty ※※** </smtps://leetcode-cn.com/problems/find-good-days-to-rob-the-bank/solution/letmefly- fen-lei-tao-lun-on-o1-by-letmef-1jgw/](https://img-blog.csdnimg.cn/img_convert/ca4a6ec46181f3756420620dbe776075.jpeg)
t i m e = 0 time=0 time=In the case of 0, special consideration should be given to inserting links and pictures.
Therefore we use two variables lian X u X ia D ays lianXuXiaDaysl ian X u X ia D a ys (representing non-increasing days) andcould A s U p 4 B egin couldAsUp4Beginco u l d A s U p 4 B e g in (The day from now on when non-decreasing can start)
That is to say, in consecutive lian X u X ia D ays lianXuXiaDaysl ian X u X ia D a ys after non-increasing days, iflian X ul ian X u X ia D a ys≥ti im e , then as long asthe continuoustime timetodayTim e is not decreasing day by day, today is the "robbery day".
So we are in lian X u X ia D ays ≥ time lianXuXiaDays\geq timel ian X u X ia D a ys≥when t im e , you can changecould A s U p 4 B egin couldAsUp4Beginco u l d A s U p 4 B e g in Mark it as today.
If the time aftert im e days and above are not decreasing, then the recordedcould A s U p 4 B egin couldAsUp4Beginco u l d A s U p 4 B e g in is a "robbery day."
Therefore, in the backward traversal, if it is still in the non-decreasing state, it can be judged whether there could A s U p 4 B egin couldAsUp4Beginco u l d A s U p 4 B e g in , if there is (≠ − 1 \neq -1=− 1 ) Just judge today’s distancecould A s U p 4 B egin couldAsUp4Beginco u l d A s U p 4 B e g in whether≥ time \geq time≥t im e days if≥ time \geq time≥t im e, Employmentcould A s U p 4 B egin couldAsUp4Beginco u l d A s U p 4 B e g in the continuoustime timet im e days are non-decreasing, socould A s U p 4 B egin couldAsUp4Beginco u l d A s U p 4 B e g in is a robbery day.
For a more detailed description, please refer to the comments
AC code
C++
class Solution {
public:
vector<int> goodDaysToRobBank(vector<int>& security, int time) {
if (!time) {
// time = 0,每天都是“打劫日”
vector<int> ans(security.size()); // 答案共有security.size()天
for (int i = 0; i < security.size(); i++) {
ans[i] = i; // 第i个答案是第i天
}
return ans;
}
vector<int> ans;
int lianXuXiaDays = 0; // 连续↓或→的天数
int couldAsUp4Begin = -1; // 最早可以认为是开始连续上升的那一天 | 如果couldAsUp4Begin=a≠-1,说明第a天之前至少有time天的非递增
for (int i = 1; i < security.size(); i++) {
// 从第二天开始遍历
if (security[i] < security[i - 1]) {
// ↓
lianXuXiaDays++; // 连续非递增天数++
if (lianXuXiaDays >= time) {
// 如果连续非递增天数≥time,那么今天之前就有≥time的非递减
couldAsUp4Begin = i; // 从今天开始可以非递减了
}
else {
// 还没有连续非递增time天
couldAsUp4Begin = -1;
}
}
else if (security[i] == security[i - 1]) {
// 今天和昨天相等,也就是说既符合非递增又符合非递减
lianXuXiaDays++; // 符合非递增,连续非递增天数++
if (couldAsUp4Begin != -1) {
// 前面有≥time的非递减,并且从那天起没有递增的一天 | Lable1
if (i - couldAsUp4Begin >= time) {
// 如果今天距离那天≥time,那天就是抢劫日
ans.push_back(couldAsUp4Begin); // 先把抢劫日添加到答案中去
if (security[couldAsUp4Begin + 1] <= security[couldAsUp4Begin]) {
// 如果抢劫日的下一天仍然是非递增,那么下一天之前肯定有至少time天的非递增
couldAsUp4Begin++; // 下一天也可以作为开始非递减的一天
}
else {
// 否则
couldAsUp4Begin = -1; // 下一天>这个抢劫日,说明下一天必不满足“前面有至少time天的非递增”
}
}
}
else {
// couldAsUp4Begin = -1
if (lianXuXiaDays >= time) {
// 连续非递增天数≥time
couldAsUp4Begin = i; // 从今天起可以开始非递减了
}
}
}
else {
// 今 > 昨
lianXuXiaDays = 0; // 连续非递减天数中断
if (couldAsUp4Begin != -1) {
// 这个同理于上面的“Lable1”处
if (i - couldAsUp4Begin >= time) {
ans.push_back(couldAsUp4Begin);
if (security[couldAsUp4Begin + 1] <= securmai ty[coul AsUp4Begin]) {
couldA Up4B gectin++;
}
已完成 else {
}
couldA }
}
Up4Begin = -1;
}
}
}
}
return ans; // 返回答案即可
}
};
Method Two
Time complexity O ( n ) O(n)O ( n ) , space complexity O(n), difficulty※
This method is easier to implement than the previous method, but the space complexity is higher than the previous method.
We can use O ( n ) O(n)The time complexity of O ( n ) is to find the "number of consecutive non-increasing days before" and "the number of consecutive non-decreasing days after" for each day.
xia [i] xia[i]x ia [ i ] display No.iiThere are non-increasing days before i day,shang [ i ] shang[i]s han g [ i ] display No.iiHow many days before i day are non-decreasing
Specific method: traverse the array from front to back, if今天≤昨天
, then
xia[i] = xia[i - 1] + 1
; otherwise,
xia[i] = 0
. Initial value
xia[0] = 0
Traverse the array from back to front, if
今天≤昨天
, then
shang[i] = shang[i + 1] + 1
; otherwise,
shang[i] = 0
. initial value
shang[security.size() - 1] = 0
Then we traverse each day, if a day satisfies xia [ i ] ≥ time xia[i]\geq timexia [ i ] _≥time 和 s h a n g [ i ] ≥ t i m e shang[i] \geq time shang [ i ] _ _≥t im e , this day is robbery day.
AC code
C++
class Solution {
public:
vector<int> goodDaysToRobBank(vector<int>& security, int time) {
vector<int> xia(security.size());
vector<int> shang(security.size());
xia[0] = 0, shang[shang.size() - 1] = 0;
for (int i = 1; i < security.size(); i++) {
xia[i] = security[i] > security[i - 1] ? 0 : xia[i - 1] + 1;
}
for (int i = security.size() - 2; i >= 0; i--) {
shang[i] = security[i] > security[i + 1] ? 0 : shang[i + 1] + 1;
}
vector<int> ans;
for (int i = 0; i < security.size(); i++) {
if (xia[i] >= time && shang[i] >= time)
ans.push_back(i);
}
return ans;
}
};
The article is published simultaneously on CSDN. It is not easy to be original. Please attach the link to the original article after reprinting with the author's consent ~
Tisfy: https://letmefly.blog.csdn.net/article/details/133324938