1、题目描述
给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
提示:
- 1 <= nums.length <= 104
- -105 <= nums[i] <= 105
进阶:你可以设计一个时间复杂度为 O(n) 的解决方案吗?
2、示例
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
3、题解
解法一:
基本思想:单调栈,维持一个单调栈。如果栈顶元素大于当前元素,说明位置需要调整,更新调整位置的结束位置就是当前位置,用upper_bound找到调整位置的起始位置。否则继续入栈
解法二:
基本思想:两次循环遍历,时间复杂度O(n)
- 从左到右循环,记录最大值为maxv,若nums[i]<maxv, 则表明位置i需要调整, 记录需要调整的最大位置right=i;
- 从右到左循环,记录最小值为minv, 若nums[i]>minv, 则表明位置i需要调整,记录需要调整的最小位置left=i.
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<climits>
using namespace std;
class Solution {
public:
int findUnsortedSubarray(vector<int>& nums) {
//基本思想:单调栈,维持一个单调栈
//如果栈顶元素大于当前元素,说明位置需要调整,更新调整位置的结束位置就是当前位置,用upper_bound找到调整位置的起始位置
//否则继续入栈
vector<int> st;
int start=nums.size(),finish=0;
for(int i=0;i<nums.size();i++)
{
if(!st.empty()&&st.back()>nums[i])
{
finish=i;
auto iter=upper_bound(st.begin(),st.end(),nums[i]);
start=min(start,int(iter-st.begin()));
st.insert(iter,nums[i]);
}
else
st.push_back(nums[i]);
}
return max(finish-start+1,0);
}
};
class Solution1 {
public:
int findUnsortedSubarray(vector<int>& nums) {
//基本思想:两次遍历,时间复杂度O(n)
//从左到右循环,记录最大值为maxv,若nums[i]<maxv, 则表明位置i需要调整, 记录需要调整的最大位置right=i;
//从右到左循环,记录最小值为minv, 若nums[i]>minv, 则表明位置i需要调整,记录需要调整的最小位置left=i.
int right=0,left=nums.size()-1,maxv=INT_MIN,minv=INT_MAX;
for(int i=0;i<nums.size();i++)
{
if(nums[i]<maxv)
right=i;
maxv=max(maxv,nums[i]);
}
for(int i=nums.size()-1;i>=0;i--)
{
if(nums[i]>minv)
left=i;
minv=min(minv,nums[i]);
}
return right==left?0:max(right-left+1,0);
}
};
int main()
{
Solution1 solute;
vector<int> nums={2,6,4,8,10,9,15};
cout<<solute.findUnsortedSubarray(nums)<<endl;
return 0;
}