LeetCode HOT100 - 最短无序连续子数组

考虑应该是什么样的

如果我们有已经排完序的数组

那么和排完序数组前缀和后缀相同的不需要修改,其他的是需要进行排序的部分

O(n) 情况下,我们可以先去找哪些是必须要被排序的

因为只能排序一次,所以数组中的逆序对是一定要被操作的,所以我们维护这些的最小值和最大值

这样我们相当于得到了一个要操作的区间

但是这个区间可能还不是完整的区间

因为比如当前数组的前缀虽然是有序的,但是和实际排完序的数组并不是重叠的

所以从数组的前缀和后缀再做一次遍历

前缀:如果当前元素大于要操作区间中的最小值,因为排序完是有序的,所以它也应该在排序区间中

后缀:如果当前元素小于要操作区间中的最大值,同理

class Solution {
public:
    int findUnsortedSubarray(vector<int>& a) {
        int n = a.size();
        int ansl = n + 5, ansr = -1;
        for (int i = 1; i < n; i++) {
            if (a[i] < a[i - 1]) {
                ansl = min(ansl, i - 1);
                ansr = max(ansr, i);
            }
            cout << ansl << ' ' << ansr << '\n';
        }
        if (ansl == n + 5) {
            return 0;
        }
        int mn = *min_element(a.begin() + ansl, a.begin() + ansr + 1);
        int mx = *max_element(a.begin() + ansl, a.begin() + ansr + 1);
        cout << mn << ' ' << mx << '\n';
        for (int i = 0; i < ansl; i++) {
            if (a[i] > mn) {
                ansl = min(ansl, i);
                break;
            }
        }
        cout << ansl << ' ' << ansr << '\n';
        for (int i = n - 1; i > ansr; i--) {
            if (a[i] < mx) {
                ansr = max(ansr, i);
                break;
            }
        }
        cout << ansl << ' ' << ansr << '\n';
        return ansr - ansl + 1;
    }
};

不过这样运行的有些慢

https://leetcode.cn/problems/shortest-unsorted-continuous-subarray/solutions/422614/si-lu-qing-xi-ming-liao-kan-bu-dong-bu-cun-zai-de-

参考这篇题解
排完序后,实际上就是最大值会在最后一位,最小值会在第一位

所以从前往后扫,维护当前的最大值,小于这个最大值的是一定要被排序的(包含了我们前面逆序对的思路),同理,从后往前扫,大于最小值的也是要被排序的

这样运行的次数可以减少

class Solution {
public:
    int findUnsortedSubarray(vector<int>& a) {
        int n = a.size();
        int mx = a[0];
        int ansr = -1;
        for (int i = 1; i < n; i++) {
            if (a[i] < mx) {
                ansr = i;
            } else {
                mx = a[i];
            }
        }
        int mn = a.back();
        int ansl = 0;
        for (int i = n - 2; i >= 0; i--) {
            if (a[i] > mn) {
                ansl = i;
            } else {
                mn = a[i];
            }
        }
        return ansr - ansl + 1;
    }
};
posted @ 2026-05-11 18:13  rdcamelot  阅读(10)  评论(0)    收藏  举报