【Leetcode刷题】【581】最短无连续子数组

题目描述

给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

你找到的子数组应是最短的,请输出它的长度。

示例:
输入: [2, 6, 4, 8, 10, 9, 15]
输出: 5
解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。

思路

这个方法背后的想法仍然是选择排序。我们需要找到无序子数组中最小元素和最大元素分别对应的正确位置,来求得我们想要的无序子数组的边界。

为了达到这一目的,此方法中,我们使用 栈 。我们从头遍历 nums数组,如果遇到的数字大小一直是升序的,我们就不断把对应的下标压入栈中,这么做的目的是因为这些元素在目前都是处于正确的位置上。一旦我们遇到前面的数比后面的数大,也就是 nums[j] 比栈顶元素小,我们可以知道 nums[j] 一定不在正确的位置上。

为了找到 nums[j] 的正确位置,我们不断将栈顶元素弹出,直到栈顶元素比 nums[j] 小,我们假设栈顶元素对应的下标为 k ,那么我们知道 nums[j] 的正确位置下标应该是 k+1 。

我们重复这一过程并遍历完整个数组,这样我们可以找到最小的 k, 它也是无序子数组的左边界

类似的,我们逆序遍历一遍 numsnums 数组来找到无序子数组的右边界。这一次我们将降序的元素压入栈中,如果遇到一个升序的元素,我们像上面所述的方法一样不断将栈顶元素弹出,直到找到一个更大的元素,以此找到无序子数组的右边界。

public class Solution {
    public int findUnsortedSubarray(int[] nums) {
        Stack < Integer > stack = new Stack < Integer > ();
        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就是右边界
                r = Math.max(r, stack.pop());
            stack.push(i);
        }
        return r - l > 0 ? r - l + 1 : 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值