Find All Good Indices

Find All Good Indices

You are given a 0-indexed integer array nums of size $n$ and a positive integer $k$.

We call an index $i$ in the range $k \leq i < n - k$ good if the following conditions are satisfied:

  • The $k$ elements that are just before the index $i$ are in non-increasing order.
  • The $k$ elements that are just after the index $i$ are in non-decreasing order.

Return an array of all good indices sorted in increasing order.

Example 1:

Input: nums = [2,1,1,1,3,4,1], k = 2
Output: [2,3]
Explanation: There are two good indices in the array:
- Index 2. The subarray [2,1] is in non-increasing order, and the subarray [1,3] is in non-decreasing order.
- Index 3. The subarray [1,1] is in non-increasing order, and the subarray [3,4] is in non-decreasing order.
Note that the index 4 is not good because [4,1] is not non-decreasing.

Example 2:

Input: nums = [2,1,1,2], k = 2
Output: []
Explanation: There are no good indices in this array.

Constraints:

$ n == nums.length$
$3 \leq n \leq {10}^{5}$
$1 \leq nums[i] \leq {10}^{6}$
$1 \leq k \leq n / 2$

 

解题思路

  做这题的时候很容易想到对于每一个$i$,可以直接每次暴力枚举区间$[i-k,i-1]$和$[i+1,i+k]$看看是否满足要求,但这样做会超时,然后又发现这相当于询问一个区间是否满足非递增或非递减,因此比赛的时候直接用线段树去实现了。

  AC代码如下:

 1 const int N = 1e5 + 10;
 2 
 3 class Solution {
 4 public:
 5     struct Node {
 6         int l, r;
 7         bool f1, f2;
 8     }tr[N * 4];
 9     vector<int> a;
10     
11     void build(int u, int l, int r) {
12         if (l == r) {
13             tr[u] = {l, r, true, true};
14         }
15         else {
16             int mid = l + r >> 1;
17             build(u << 1, l, mid);
18             build(u << 1 | 1, mid + 1, r);
19             tr[u] = {l, r, tr[u << 1].f1 && tr[u << 1 | 1].f1 && a[mid] >= a[mid + 1], tr[u << 1].f2 && tr[u << 1 | 1].f2 && a[mid] <= a[mid + 1]};
20         }
21     }
22     
23     Node query(int u, int l, int r) {
24         if (tr[u].l >= l && tr[u].r <= r) return tr[u];
25         int mid = tr[u].l + tr[u].r >> 1;
26         if (r <= mid) {
27             return query(u << 1, l, r);
28         }
29         else if (l >= mid + 1) {
30             return query(u << 1 | 1, l, r);
31         }
32         else {
33             Node t1 = query(u << 1, l, r);
34             Node t2 = query(u << 1 | 1, l, r);
35             Node ret;
36             ret.f1 = t1.f1 && t2.f1 && a[mid] >= a[mid + 1];
37             ret.f2 = t1.f2 && t2.f2 && a[mid] <= a[mid + 1];
38             return ret;
39         }
40     }
41     
42     vector<int> goodIndices(vector<int>& nums, int k) {
43         int n = nums.size();
44         a = nums;
45         build(1, 0, n - 1);
46         vector<int> ans;
47         for (int i = k; i < n - k; i++) {
48             if (query(1, i - k, i - 1).f1 && query(1, i + 1, i + k).f2) ans.push_back(i);
49         }
50         return ans;
51     }
52 };

  下面给出正解,反正我是想不到的。

  先预处理一个$f(i)$,表示以$i$为右端点,且单调递减的序列的最大长度。再预处理一个$g(i)$表示以$i$为左端点,且单调递增的序列的最大长度。

  对于$f(i)$,如果有$a_{i-1} \geq a_{i}$,那么$f(i) = f(i-1)+1$;否则如果有$a_{i-1} < a_{i}$,那么$f(i) = 1$。

  同理对于$g(i)$,如果有$a_{i} \leq a_{i+1}$,那么$g(i) = g(i+1)+1$;否则如果有$a_{i} > a_{i+1}$,那么$g(i) = 1$。

  因此当我们想要判断第$i$个位置是否满足要求,就可以看是否同时满足$f(i-1) \geq k$和$g(i+1) \geq k$。

  AC代码如下:

 1 class Solution {
 2 public:
 3     vector<int> goodIndices(vector<int>& nums, int k) {
 4         int n = nums.size();
 5         vector<int> f(n), g(n);
 6         for (int i = 0; i < n; i++) {
 7             f[i] = 1;
 8             if (i && nums[i] <= nums[i - 1]) f[i] = f[i - 1] + 1;
 9         }
10         for (int i = n - 1; i >= 0; i--) {
11             g[i] = 1;
12             if (i + 1 < n && nums[i] <= nums[i + 1]) g[i] = g[i + 1] + 1;
13         }
14         
15         vector<int> ans;
16         for (int i = k; i < n - k; i++) {
17             if (f[i - 1] >= k && g[i + 1] >= k) ans.push_back(i);
18         }
19         return ans;
20     }
21 };

 

参考资料

  力扣第312场周赛:https://www.bilibili.com/video/BV13Y4y1K7eU

posted @ 2022-09-25 16:33  onlyblues  阅读(16)  评论(0编辑  收藏  举报
Web Analytics