【贪心-4】581.最短无序连续子数组

题目描述:

给你一个整数数组 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

解题思路:

方法一:双指针(贪心思想,最优)

思路:

数组可以分成三段:有序前缀 + 无序中段 + 有序后缀。

  • 左边界 :从左往右扫描,维护左边最大值 maxNum。如果 nums[i] < maxNum,说明 i 在无序区域内,更新 low = i。

  • 右边界 :从右往左扫描,维护右边最小值 minNum。如果 nums[i] > minNum,说明 i 在无序区域内,更新 high = i。

  • 结果 :low - high + 1 就是最短无序子数组的长度。

代码实现:

cpp 复制代码
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n = nums.size();
        if (n <= 1) return 0;
        
        int low = 0, high = n - 1;
        int maxNum = nums[0], minNum = nums[n - 1];
        
        for (int i = 1; i < n; i++) {
            // 从左往右:维护最大值,找最右边的乱序位置
            maxNum = max(maxNum, nums[i]);
            if (nums[i] < maxNum) low = i;
            
            // 从右往左:维护最小值,找最左边的乱序位置
            minNum = min(minNum, nums[n - 1 - i]);
            if (nums[n - 1 - i] > minNum) high = n - 1 - i;
        }
        
        return low > high ? low - high + 1 : 0;
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n) 一次遍历
空间复杂度 O(1) 只用常数个变量

优缺点:

优点 缺点
✅ 时间复杂度 O(n),最优 ❌ 思路不直观,需要理解"乱序"的判断
✅ 空间复杂度 O(1) ❌ 边界条件容易写错(如 low > high 的判断)
✅ 一次遍历同时找左右边界
✅ 面试首选

方法二:排序 + 双指针

思路:

  1. 把原数组复制一份并排序。

  2. 对比排序后的数组和原数组:

    • 从左往右找到第一个不同的位置 l

    • 从右往左找到最后一个不同的位置 r

  3. r - l + 1 就是最短无序子数组的长度。

代码实现:

cpp 复制代码
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        vector<int> sorted = nums;
        sort(sorted.begin(), sorted.end());
        
        int l = 0, r = nums.size() - 1;
        while (l <= r && nums[l] == sorted[l]) l++;
        while (l <= r && nums[r] == sorted[r]) r--;
        
        return r - l + 1;
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n log n) 排序
空间复杂度 O(n) 复制一份数组

优缺点:

优点 缺点
✅ 思路直观,容易理解 ❌ 时间复杂度 O(n log n),不是最优
✅ 代码简洁,不易出错 ❌ 需要额外 O(n) 空间
✅ 适合快速写出答案 ❌ 面试官可能追问"能否 O(n)"

两种方法对比:

对比维度 双指针 + 线性扫描 排序 + 双指针
时间复杂度 O(n) O(n log n)
空间复杂度 O(1) O(n)
代码复杂度 中等 简单
是否修改原数组 ❌ 不修改 ❌ 不修改
相关推荐
weixin_307779131 小时前
从“人操作仪器”到“Agent 自主发现”:OPL 金属材料自驱动实验室 MVP 技术论述
开发语言·人工智能·算法·架构
释厄6231 小时前
01AB 基本元理——任何智能体的三元法理·0=1→0≠1法理跃迁为天理
人工智能·windows·算法·microsoft·机器学习
Omics Pro1 小时前
经典多组学整合算法→商用云平台
数据库·人工智能·算法·机器学习·自然语言处理
ting94520001 小时前
深度拆解|1752vc Pitch Deck Analyzer 底层技术架构与核心算法原理
人工智能·算法·架构
无名猿1 小时前
list 与 forward_list:链表真的比 vector 快吗
c++·性能优化·stl·内存管理·标准库
笑鸿的学习笔记2 小时前
C++笔记之SIMD与SSE指令集
开发语言·c++·笔记
贾斯汀frank2 小时前
基于 Java + Playwright 实现网站自动访问与数据采集
算法
早睡早起不秃头&2 小时前
【架构】- 移动机器人系统的插件化:让定位算法独立演进
算法·架构
汉克老师2 小时前
GESP2026年9月认证C++一级( 第二部分判断题(1~10题)精讲
c++·gesp·小学生·学c++编程