Leecode Hot100 刷题笔记本-排序(C++版)

82 阅读1分钟
  1. 581. 最短无序连续子数组 中等

581. 最短无序连续子数组

Screen Shot 2023-09-02 at 7.43.35 PM.png

解法1: 排序
  • 先检查数组是否已经是有序的,如果是有序的就返回0,
  • 否则,复制一份原数组并对其进行排序。
  • 然后,从左边开始找到第一个不匹配的元素,以及从右边开始找到第一个不匹配的元素,它们之间的区间就是未排序的连续子数组。
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        // 检查数组是否已经是有序的
        if (is_sorted(nums.begin(), nums.end())) {
            return 0; // 如果有序,返回0
        }
        
        // 复制原数组并对副本进行排序
        vector<int> numsSorted(nums);
        sort(numsSorted.begin(), numsSorted.end());
        
        // 从左边开始找第一个不匹配的元素的位置
        int left = 0;
        while (nums[left] == numsSorted[left]) {
            left++;
        }
        
        // 从右边开始找第一个不匹配的元素的位置
        int right = nums.size() - 1;
        while (nums[right] == numsSorted[right]) {
            right--;
        }
        
        // 计算未排序连续子数组的长度
        return right - left + 1;
    }
};

Screen Shot 2023-09-02 at 7.57.14 PM.png

解法2: 一次遍历
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n = nums.size(); // 获取数组的大小
        int maxn = INT_MIN, right = -1; // 初始化最大值和右边界
        int minn = INT_MAX, left = -1; // 初始化最小值和左边界

        for (int i = 0; i < n; i++) {
            // 从左往右遍历数组,找到不按照升序排序的最大值和右边界
            if (maxn > nums[i]) {
                right = i; // 如果当前元素小于之前的最大值,更新右边界
            } else {
                maxn = nums[i]; // 否则,更新最大值
            }

            // 从右往左遍历数组,找到不按照升序排序的最小值和左边界
            if (minn < nums[n - i - 1]) {
                left = n - i - 1; // 如果当前元素大于之前的最小值,更新左边界
            } else {
                minn = nums[n - i - 1]; // 否则,更新最小值
            }
        }

        // 如果 right 仍然等于 -1,表示数组已经有序,返回 0
        return right == -1 ? 0 : right - left + 1;
    }
};

Screen Shot 2023-09-02 at 8.04.47 PM.png