3350. 检测相邻递增子数组 II
问题
给你一个由 n 个整数组成的数组 nums ,请你找出 k 的 最大值,使得存在 两个 相邻 且长度为 k 的 严格递增 子数组。具体来说,需要检查是否存在从下标 a 和 b (a < b) 开始的 两个 子数组,并满足下述全部条件:
这两个子数组 nums[a..a + k - 1] 和 nums[b..b + k - 1] 都是 严格递增 的。
这两个子数组必须是 相邻的,即 b = a + k。
返回 k 的 最大可能 值。
子数组 是数组中的一个连续 非空 的元素序列。
示例 1:
输入:nums = [2,5,7,8,9,2,3,4,3,1]
输出:3
解释:
从下标 2 开始的子数组是 [7, 8, 9],它是严格递增的。
从下标 5 开始的子数组是 [2, 3, 4],它也是严格递增的。
这两个子数组是相邻的,因此 3 是满足题目条件的 最大 k 值。
分析
代码
class Solution {
public:
int res = 0;
vector<int> q;
bool check(int x) {
int ll = 0, lr = x-1, rl = x, rr = 2*x-1;
while(rr < q.size()) {
bool flag = true;
for (int i = ll+1; i <= lr; i++) {
if (q[i] <= q[i-1]) {flag = false; break;}
}
if (!flag) {ll++, lr++, rl++, rr++;continue;}
for (int i = rl+1; i <= rr; i++) {
if (q[i] <= q[i-1]) {flag = false; break;}
}
if (flag) {return true;}
ll++, lr++, rl++, rr++;
}
return false;
}
int maxIncreasingSubarrays(vector<int>& nums) {
int r = nums.size() / 2 + 1;
int l = 0;
this->q = nums;
while(l + 1 < r) {
int mid = (l + r) >> 1;
if (check(mid)) {
l = mid;
} else {
r = mid;
}
}
res = l;
return res;
}
};
关于检查函数,这个复杂度过高,一个一个滑动,浪费时间。
猜想:滑动窗口可以使用双端队列高效管理。
class Solution {
public:
int res = 0;
vector<int> q;
//可以这样,使用滑动窗口来做这个题,维护两个滑窗,然后判断每次
//滑动的时候判断当前窗口的大小是否等于k,如果两个窗口都等于
//k,那么说明可以构成连续的两个相邻严格递增子数组了
bool check(int x) {
deque<int> q1, q2;
for (int i = 0, j = x; j < q.size(); i++, j++) {
if (q1.size() && q1.front() < i-x+1) {
q1.pop_front();
} if (q2.size() && q2.front() < j-x+1) {
q2.pop_front();
} while (q1.size() && q[q1.back()] >= q[i]) {
q1.pop_back();
} while (q2.size() && q[q2.back()] >= q[j]) {
q2.pop_back();
}
q1.push_back(i); q2.push_back(j);
if (q1.size() == x && q2.size() == x) {
return true;
}
}
return false;
}
int maxIncreasingSubarrays(vector<int>& nums) {
int r = nums.size() / 2 + 1;
int l = 0;
this->q = nums;
while(l + 1 < r) {
int mid = (l + r) >> 1;
if (check(mid)) {
l = mid;
} else {
r = mid;
}
}
res = l;
return res;
}
};

浙公网安备 33010602011771号