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 ki<nk 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
3n105
1nums[i]106
1kn/2

 

解题思路

  做这题的时候很容易想到对于每一个i,可以直接每次暴力枚举区间[ik,i1][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),如果有ai1ai,那么f(i)=f(i1)+1;否则如果有ai1<ai,那么f(i)=1

  同理对于g(i),如果有aiai+1,那么g(i)=g(i+1)+1;否则如果有ai>ai+1,那么g(i)=1

  因此当我们想要判断第i个位置是否满足要求,就可以看是否同时满足f(i1)kg(i+1)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 @   onlyblues  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示