✨1574. 删除最短的子数组使剩余数组有序✨
力扣C++打卡(3.25)!✊✊✊🌈大家好!本篇文章将介绍关于数组的OJ题,题目来自力扣:1574. 删除最短的子数组使剩余数组有序,展示代码语言暂时为:C++代码 😇。
🔒1、题目:
给你一个整数数组 arr ,请你删除一个子数组(可以为空),使得 arr 中剩下的元素是非递减的。
一个子数组指的是原数组中连续的一个子序列。
请你返回满足题目要求的最短子数组的长度。
🌲 示例 1🌲:
输入:arr = [1,2,3,10,4,2,3,5]
输出:3
解释:我们需要删除的最短子数组是 [10,4,2] ,长度为 3 。剩余元素形成非递减数组 [1,2,3,3,5] 。
另一个正确的解为删除子数组 [3,10,4] 。
🌲 示例 2🌲:
输入:arr = [5,4,3,2,1]
输出:4
解释:由于数组是严格递减的,我们只能保留一个元素。所以我们需要删除长度为 4 的子数组,要么删除 [5,4,3,2],要么删除 [4,3,2,1]。
🌲 示例 3🌲:
输入:arr = [1,2,3]
输出:0
解释:数组已经是非递减的了,我们不需要删除任何元素。
🌲 示例 4🌲:
输入:arr = [1]
输出:0
❗️ 限制❗️ :
1 <= arr.length <= 10^5
0 <= arr[i] <= 10^9
来源:力扣👈
链接:https://leetcode.cn/problems/shortest-subarray-to-be-removed-to-make-array-sorted/
☀️2、思路:
题目给一个整数数组 arr ,要求删除原数组中连续的一个子序列(可以为空),使得 arr 中剩下的元素是非递减的,需要求出满足这样条件的最短的子数组长度。
最容易想到的是先保证数组一端单调递增,对另一端元素进行处理。
从这个想法出发,选择先对数组的头部元素进行删除,使得尾部剩余的元素单调递增。这就需要一个指针初始指向尾部,如果只想的元素大于前一个元素,指针前移,直到指向的元素小于前一个元素为止,这就保证了从该指针到尾部的元素时单调递增的。将该指针前的元素全部删除,便可使得 arr 中剩下的元素是非递减的。
但该结果明显不是最好的,最佳的答案可能是删除中间的一段。例如数组 [1,2,3,10,4,2,3,5],最佳答案是删除中间的 [3,10,4] 或者 [10,4,2],而不是删除头部的[1,2,3,10,4] 。
假设删除的是 arr[i+1]∼arr[j−1]之间的元素,我们需要保证:
1. arr[0]∼arr[i]非递减。
2. arr[j]∼arr[n−1]非递减。
3. arr[i]≤arr[j]。
如果我们枚举 i 和 j,然后再用 O(n)的时间判断是否满足上述条件,那么总复杂度是 O(n^3 )。但如果我们在从对i进行从小到大枚举的过程中,也从大到小枚举j,那么总复杂度将会降低至O(n^2)。
假设对于当前的 i 来说,j1 是最优的,那么这意味着这个j1是最小的满足条件 2 和条件 3 的下标。最小是因为我们要使得被删除数组 arr[i+1]∼arr[j−1] 最短。此时我们将 i 加 1,如果满足条件 1,即 arr[i+1]≥arr[i],那么i+1 所匹配的 j2 满足 j2≥j1。
因此,我们需要两个指针来维护这样的 i 和 j。实现流程如下:
🍓实现流程:
1️⃣ 得到数组大小n,数组最后一个元素下标为n-1;
2️⃣ 得到指针j,使得j到数组末端的元素都是单调递增的。初始化答案为 j 前面的元素个数
3️⃣ 从0开始枚举i,直到n-1。对于每个i,若arr[i]>arr[j],j后退,直到 arr[j]≥arr[i] 或者 j=n。
4️⃣ 此时 j−i−1 就是我们要删除的元素个数,用它来更新答案。然后令 i 等于 i+1,并保证 arr[i+1]≥arr[i],如果不满足则直接跳出循环,如果满足则继续下一轮枚举。
🌻过程模拟:
复杂度分析:
⏳时间复杂度 O(N) :其中 n 是 arr的长度。双指针 i 和 j 移动过程中,每个元素最多只会被遍历两次,所以复杂度为 O(n)。
🏠空间复杂度 O(1) :数据流长度为N,两个堆一个存入N个数据。
🔑3、代码:
class Solution {
public:
int findLengthOfShortestSubarray(vector<int>& arr) {
int n = arr.size(), j = n - 1;
while(j>0&&arr[j-1]<=arr[j]) j--;
if(j==0) return 0;
int res=j;
for(int i=0;i<n;i++){
while(j<n &&arr[j]<arr[i]) j++;
res=min(res,j-i-1);
if(i+1<n &&arr[i]>arr[i+1]){
break;
}
}
return res;
}
};
坚持打卡,继续加油!✊✊
博主水平有限,如果有疑问的可以评论区留言交流!
🚀🚀更新不易,觉得文章写得不错的小伙伴们,点赞评论关注走一波💕💕~~~谢谢啦🙏 🙏🙌 !