LeetCode 2100. A good day to rob a bank

【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 day time .
  • i The number of guards on consecutive days before the first day time is non-increasing.
  •  The number of guards is non-decreasing on i consecutive days after the first day.time

More formally, day iis 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 ysti 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 yswhen 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 timet im e days if≥ time \geq timet 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

Guess you like

Origin blog.csdn.net/Tisfy/article/details/133324938