Leetcode581 最短无序连续子数组

222 阅读1分钟

这道题有三种方法 另外,对于寻边界的问题,首先要想到单调栈,用于存放最值(或者最值位置,视情况而定)
方法一:时间复杂度O(n^2),空间复杂度O(1)
方法二:时间复杂度O(n)+O(nlogn),空间复杂度O(n)
方法三:时间复杂度O(n),空间复杂度O(n)

image.png

class Solution {
    //方法1:双指针法
    public int findUnsortedSubarray(int[] nums) {
        int l=nums.length,r=0;
        for(int i=0;i<nums.length;i++){//左指针从从开始
            for(int j=i+1;j<nums.length;j++){   //右指针从下一个位置开始,找比当前位置小的元素
                if(nums[j]<nums[i]){
                    r = Math.max(r,j);  //更新右侧
                    l = Math.min(l,i);  //更新左侧
                }
            }
        }
        return r-l<0?0:r-l+1;
    }
    //方法2:先排序
    public int findUnsortedSubarray(int[] nums) {
        //先排序,然后找出第一个和最后一个不同的位置
        int[] cloneNums = nums.clone();  //用clone方法复制数据
        Arrays.sort(cloneNums);
        int l=nums.length,r=0;
        for(int i=0;i<nums.length;i++){
            if(nums[i]!=cloneNums[i]){
                l = Math.min(l,i);
                r = Math.max(r,i);
            }
        }
        return r-l<0?0:r-l+1;
    }
    //方法3:单调栈 
    public int findUnsortedSubarray(int[] nums) {
        //但凡涉及到边界问题,首先想到单调栈,栈中存放的是最值位置(或者最值,视情况而定)
        Stack<Integer> stack = new Stack<>();
        int l = nums.length,r=0;
        for(int i=0;i<nums.length;i++){
            while(!stack.isEmpty() && nums[stack.peek()]>nums[i]){
                l = Math.min(l,stack.pop()); 
            }
            stack.push(i);
        }
        stack.clear();
        for(int i=nums.length-1;i>=0;i--){
            while(!stack.isEmpty() && nums[stack.peek()]<nums[i]){
                r = Math.max(r,stack.pop());
            }
            stack.push(i);
            
        }
        return r-l<0?0:r-l+1;
    }
}