[LeetCode]581. Shortest Unsorted Continuous Subarray 解题报告(C++)

[LeetCode]581. Shortest Unsorted Continuous Subarray 解题报告(C++)

题目描述

Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too.

You need to find the shortest such subarray and output its length.

Example 1:

Input: [2, 6, 4, 8, 10, 9, 15]
Output: 5
Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole array sorted in ascending order.

Note:

  1. Then length of the input array is in range [1, 10,000].
  2. The input array may contain duplicates, so ascending order here means <=.

题目大意

  • 给定一个数组.找到其中子串
  • 如果这个子串是有序的.那么整个数组也是有序的!
  • 找到最短的子串.并且返回它的长度.

解题思路

方法1:

  • 将它正确排序后的数组比较.找到左右分别不相等的位置.
  • 即 子串的左右边界.
  • 注意若l,r都没有改变.说明子串是有序的.
代码实现:
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        vector<int> ref;
        ref.assign(nums.begin(), nums.end());
        sort(ref.begin(), ref.end());
        int l = 0, r = 0;
        for (int i = 0; i < nums.size(); i++)
        {
            if (nums[i] != ref[i]) {
                l = i;
                break;
            }
        }
        for (int i = nums.size()-1; i >=0; i--)
        {
            if (nums[i] != ref[i]) {
                r = i;
                break;
            }
        }
        if (l==0&&r==0) {
            return 0;
        }
        return r - l + 1;
    }
};

// 简化版
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n= nums.size();int i=0,j=n-1;
        vector<int> t=nums;
        sort(t.begin(),t.end());
        while(i<n&&nums[i]==t[i]) i++;
        while(j>i&&nums[j]==nums[j]) j--;
        return j-i+1;
    }
};

方法2:

  • 求最短的无序连续子串.找到 起始和结束位置即可.
  • 遍历数组. 用start变量来记录起始位置.
  • 当 某个数字比前面的数字要小.则此时需要将这个数字向前移动,移到它应在的位置.(ps.这个移动就是类似插入排序使用的).用j来记录正确的位置.并且当start=-1和start>j时要更新.再用 i-start+1更新结果.
代码实现:
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int res = 0;
        int start = -1;
        int n = nums.size();

        for (int i = 1; i < n; i++) {
            if (nums[i] < nums[i - 1]) {
                int j = i;
                while (j > 0 && nums[j] < nums[j - 1]) {
                    swap(nums[j], nums[j - 1]);
                    --j;
                }
                if (start == -1 || start > j) {
                    start = j;
                }
                res = max(res, i - start + 1);
            }
        }
        return res;
    }
};

方法3:

  • 下面这种方法溜得飞起! 空间复杂度O(1) 时间复杂度O(n)
  • 用两个变量mx和mn来代替上面的有序数组.
  • 初始化 最小值mn为最后一个数字. 最大值mx为第一个数字.
  • 从第二个数字开始遍历.
  • 将mx和nums[i]的最大值给mx. 然后比较mx和nums[i]的大小.若mx>nums[i] 则end=i;
  • 将mn和nums[n-1-i]的最小值赋值给mn.然后比较mn和nums[n-1-i]的大小.若mn
代码实现:
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n = nums.size();
        int start=-1,end=-2;
        int mx=nums[0],mn=nums[n-1];
        for (int i = 1; i < n; i++) {
            mx= max(mx,nums[i]);
            mn = min(mn,nums[n-1-i]);
            if(mx>nums[i]) end=i;
            if(mn<nums[n-1-i]) start=n-1-i;
        }
        return end-start+1;
    }
};

小结

  • 还是写不出像别人那样的代码.主要是思路不对.唉.练习啊.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值