力扣刷题笔记 → 581. 最短无序连续子数组| 8月更文挑战

173 阅读1分钟

题目

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

请你找出符合题意的 最短 子数组,并输出它的长度。

示例

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

示例2:
输入: nums = [1,2,3,4]
输出: 0

示例 3:
输入: nums = [1]
输出: 0

提示

  • 1 <= nums.length <= 104
  • -105 <= nums[i] <= 105

解题思路

  1. 按照题目的提示,我们需要找到一个连续的子数组,对该子数组进行排序使得整个数组都是升序排列的,那么这里可以得到四种情况:

    • [0,1,···,子数组]
    • [0,1,···,子数组,···,n - 1, n]
    • [子数组,···, n - 1, n]
    • [子数组]
  2. 不管是那种情况,我们都只需要对一个子数组进行排序即可,其余不在子数组范围内的元素均已排好序,可以不用关注,那这里我们可以通过双指针来确定出子数组的左右边界,即可得到结果:

    • 从左边开始找到最后一位比前面元素小的元素
    • 从右边开始找到最后一位比后面元素大的元素

代码实现

class Solution {
    public int findUnsortedSubarray(int[] nums) {
        int n = nums.length;
        // 定义左右边界两个指针,以及两个做判断使用的变量
        int max = Integer.MIN_VALUE, left = -1, min = Integer.MAX_VALUE, right = n;

        // 双向遍历数组,这里是 i 跟 j 分别遍历了一遍
        for(int i = 0, j = n - 1; i < n; ++i, --j){
            // 当前元素小于等于前面的元素,更新左边界指针的位置
            if(max > nums[i]){
                left = i;
            }else{
                max = nums[i];
            }

            // 当前元素大于后面的元素,更新右边界指针的位置
            if(min < nums[j]){
                right = j;
            }else{
                min = nums[j];
            }
        }

        // 如果left指针没有移动,表示该数组为顺序数组,返回结果 0。
        // 否则,返回子数组区间长度
        return left == -1 ? 0 : left - right + 1;
    }
}

复杂度分析

时间复杂度:O(n),两个指针都只分别遍历了一遍。

时间复杂度:O(1),常量级。

最后

文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!

如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!

题目出处:leetcode-cn.com/problems/sh…