LeetCode 2970 | 统计移除递增子数组的数目
题目
如果 nums 的一个子数组满足:移除这个子数组后剩余元素严格递增,那么我们称这个子数组为移除递增子数组。比方说,[5, 3, 4, 6, 7] 中的 [3, 4] 是一个移除递增子数组,因为移除该子数组后,[5, 3, 4, 6, 7] 变为 [5, 6, 7] ,是严格递增的。
请你返回 nums 中 移除递增 子数组的总数目。
注意 ,剩余元素为空的数组也视为是递增的。
示例 1:
输入:nums = [1,2,3,4]
输出:10
解释:10 个移除递增子数组分别为:[1], [2], [3], [4], [1,2], [2,3], [3,4], [1,2,3], [2,3,4] 和 [1,2,3,4]。移除任意一个子数组后,剩余元素都是递增的。注意,空数组不是移除递增子数组。
💡1. 可以注意到,需要移除的是一个在nums里连续的子数组,所以我们可以用双指针L、R枚举子数组的两端。
💡2. 如果[0, L]是严格递增的,则移除递增子数组为[L + 1, R];那么[0, L - 1]也是严格递增的,[L, R]也是移除递增子数组。
✨对于R = n时
我们可以找到最大的L,使得[0, L]严格递增,那么[L + 1, R]为移除递增子数组,子数组的左端点可以从 0->L,总计 L + 1 个子数组。如果L < R,那么[L + 1, R]也存在,需要子数组加一。
✨子数组的右端点R继续右移(n - 1) -> 0
此时,需要子数组的左右两端合并能组成一个严格递增数组。
左边的数字我们在前面得到L的时候已经判断过严格递增了,我们还需要判断右边的数字是严格递增的,在R每改变一次的时候判断一次当前数字是否比后一个低。
if(nums[r] >= nums[r + 1]) break;
同时还需要判断左右两边的数组能否合并:如果nums[L]比nums[R]大的话,我们需要将L指针左移,直到nums[L]小于nums[R]。
while(l >= 0 && nums[l] >= nums[r]) l--;
💟代码
int incremovableSubarrayCount(vector<int>& nums) {
int ans = 0, n = nums.size(), l = 0, r = n - 1;
while(l < n - 1 && nums[l] < nums[l + 1]) l++;
ans += l + 1;
if(l < r) ans++;
while(l >= 0 && nums[l] >= nums[r]) l--;
ans += l + 1;
if(l < r - 1) ans++;
for(r = n - 2; r >= 0; r--){
if(nums[r] >= nums[r + 1]) break;
while(l >= 0 && nums[l] >= nums[r]) l--;
ans += l + 1;
if(l < r - 1) ans++;
}
return ans;
}

浙公网安备 33010602011771号