LeetCode 1574. 删除最短的子数组使剩余数组有序***

具体思想:

本题目可以抽象一下;

总的来说,由于删除一个序列,保证整体有序,因此可以将整体序列划分为三个部分:

l e f t , m i d , r i g h t left,mid,right left,mid,right

其中left和right都为有序,mid则是要删除元素,且left和right都为非递减序列;

首先贪心,从头部尾部向中间扩散,得到初始的left和rgiht;

此时问题就变成,两个有序序列,如果拼成一个最长的有序序列;

这个问题可以巧妙的用双指针解决;

指针l,r分别指向left和right的头部;

并且计算当 a r r [ l ] < = a r r [ r ] arr[l]<=arr[r] arr[l]<=arr[r]时,距离为少;

这里注意一下递增方式;

a r r [ l ] < = a r r [ r ] arr[l]<=arr[r] arr[l]<=arr[r],l++;

a r r [ l ] > a r r [ r ] arr[l]>arr[r] arr[l]>arr[r],r++;

原因是当 a r r [ l ] < = a r r [ r ] arr[l]<=arr[r] arr[l]<=arr[r]时,r后面的所有元素都肯定比l所指向的元素大,所以不用向后遍历,以l为第一部分结尾的序列最佳也就是那么长了;

具体代码:

class Solution {
public:
    int findLengthOfShortestSubarray(vector<int>& arr) {
        int left=0,right=arr.size()-1,n=arr.size();
        while(left+1<arr.size()&&arr[left+1]>=arr[left]){
            left++;
        }
        if(left==arr.size()-1)
            return 0;
        while(right-1>=0&&arr[right-1]<=arr[right]){
            right--;
        }
        int ret=min(right,n-1-left);//直接删除左区间或者右区间;
        int l=0,r=right;
        while(l<=left&&r<n){
            if(arr[l]<=arr[r]){
                ret=min(ret,r-l-1);
                l++;
            }else{
                r++;
            }
        }
        return ret;
    }
};

你可能感兴趣的:(LeetCode刷题记录,leetcode,算法,贪心算法)