《LeetCode之每日一题》:113.最短无序连续子数组

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:113.最短无序连续子数组相关的知识,希望对你有一定的参考价值。

最短无序连续子数组


题目链接: 最短无序连续子数组

有关题目

给你一个整数数组 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
-10^5 <= nums[i] <= 10^5
进阶:你可以设计一个时间复杂度为 O(n) 的解决方案吗?

题解

法一:排序
代码一:

int Is_sorted(int* nums, int numsSize){
    for (int i = 0; i < numsSize - 1; i++){
        if (nums[i] > nums[i + 1])
            return 0;
    }
    return 1;
}

int cmp(int* a, int* b){
    return *a - *b;
}
int findUnsortedSubarray(int* nums, int numsSize){
    if (Is_sorted(nums, numsSize)) //特判
        return 0;

    int arr[numsSize];
    memcpy(arr, nums, numsSize * sizeof(int));
    qsort(arr, numsSize, sizeof(int), cmp);

    int l = 0, r = numsSize - 1;
    while(nums[l] == arr[l]) l++;
    while(nums[r] == arr[r]) r--;

    return r - l + 1;
}

代码二:


int cmp(int* a, int* b){
    return *a - *b;
}
int findUnsortedSubarray(int* nums, int numsSize){
    int ans = 0, l = 0, r = numsSize - 1;


    int arr[numsSize];
    memcpy(arr, nums, numsSize * sizeof(int));
    qsort(arr, numsSize, sizeof(int), cmp);
    while(l < numsSize && arr[l] == nums[l]) l++;
    while(r >= 0 && arr[r] == nums[r]) r--;
    return l == numsSize ? 0 : r - l + 1 ;
}


法二:单调栈

int findUnsortedSubarray(int* nums, int numsSize){
    int n = numsSize;
    int stk[n], stkSize = 0;
    int l = n - 1, r = 0;
    for (int i = 0; i < n; i++){//寻找左边界
        while(stkSize && nums[stk[stkSize - 1]] > nums[i]){
            l = fmin(l, stk[stkSize - 1]);
            stkSize--;
        }
        stk[stkSize++] = i;
    }

    stkSize = 0;//重置栈
    for (int i = n - 1; i >= 0; i--){//寻找右边界
        while(stkSize && nums[stk[stkSize - 1]] < nums[i]){
            r = fmax(r, stk[stkSize - 1]);
            stkSize--;
        }
        stk[stkSize++] = i;
    }
    return r - l > 0 ? r - l + 1 : 0;//示例[1]此时r 与 l 重合
}

时间复杂度:O(N)
空间复杂度:O(N)
法三:一次遍历

思想:
无序子数组中最小元素的正确位置可以决定左边界,最大元素的正确位置可以决定右边界

代码一:

int findUnsortedSubarray(int* nums, int numsSize) {
//if (is_sorted(nums.begin(), nums.end())){
//            return 0;
  //      }
    int n = numsSize;
    int maxn = INT_MIN, right = -1;
    int minn = INT_MAX, left = -1;
    for (int i = 0; i < n; i++) {

        //maxn与right从左往右寻找到 非排序与排序之间的过渡线
        //找到比左边更大的数,我们更新maxn,
        if (maxn > nums[i]) {
            right = i;//[1,3,2,3,3],注意是发现大于nums[i]的数字更新下标
        } else {
            maxn = nums[i];//2 6
        }

        //minn与left从右往左寻找到 非排序与排序之间的过渡线
        //找到比右边位置更小的数,我们更新minn,不然的更新下标
        if (minn < nums[n - i - 1]) {
            left = n - i - 1;//6
        } else {
            minn = nums[n - i - 1];//15 9
        }
    }
    return right == -1 ? 0 : right - left + 1;
}

代码二:

int findUnsortedSubarray(int* nums, int numsSize){
    int n = numsSize;
    int i = 0, j = n - 1;
    int minn = INT_MAX, maxn = INT_MIN;
    
    //初始确定i j范围
    while(i < n - 1 && nums[i] <= nums[i + 1]) i++;//等于的示例[1,3,2,3,3,3]
    while(j > 1 && nums[j - 1] <= nums[j] ) j--;

    if (i >= j) return 0;//示例[1]取等于

    //找到无序数组中最大,最小值
    for (int k = i; k <= j; k++){
        minn = fmin(minn, nums[k]);
        maxn = fmax(maxn, nums[k]);
    }

    //最终确定i j位置
    while(i >= 0 && nums[i] > minn) i--;
    while(j < n && nums[j] < maxn) j++;

    return j - i - 1;
}

以上是关于《LeetCode之每日一题》:113.最短无序连续子数组的主要内容,如果未能解决你的问题,请参考以下文章

《LeetCode之每日一题》:79.数组的度

LeetCode 581. 最短无序连续子数组/611. 有效三角形的个数/15. 三数之和/18. 四数之和(双指针)

《LeetCode之每日一题》:156.环形链表

《LeetCode之每日一题》:284.环形链表

解题报告Leecode 748. 最短补全词——Leecode每日一题系列

解题报告Leecode 748. 最短补全词——Leecode每日一题系列