题目描述
描述:给定一个整数数组,编写一个函数,找出索引m和n,只要将索引区间[m,n]的元素排好序,整个数组就是有序的。注意:n-m尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n],若不存在这样的m和n(例如整个数组是有序的),请返回[-1,-1]。
示例:
输入: [1,2,4,7,10,11,7,12,6,7,16,18,19]
输出: [3,9]
提示:
0 <= len(array) <= 1000000
解题思路
思路1:最直观的想法是,先将原有数组a备份为b,然后使用sort对a进行排序,再一次遍历比较a和b不同的元素,并将对应的下标加入到res数组中,遍历完成后,如果res数组长度小于等于1,则不满足要求,直接返回{-1,-1},反之返回res第一个元素和最后一个元素即可。
class Solution {
public:
vector<int> subSort(vector<int>& array) {
//备份一份整数数组
vector<int> b(array);
//对原有整数数组排序
sort(array.begin(),array.end());
//存储结果元素 第一个和最后一个即为所求
vector<int> res;
//遍历排序后的数组和原有数组找到第一个不同和最后一个不同
for(int i=0;i<array.size();i++)
{
if(array[i]!=b[i])
//注意这里是下标
res.push_back(i);
}
//区间至少两个
if(res.size()<=1)
return {-1,-1};
return {res[0],res.back()};
}
};
思路2:默认数组是按照升序排序的,如果数组中出现元素a[i],其左边存在比其大的数,或者其右边存在比其小的数,那么a[i]就需要参与到排序中去。现在所需要寻找的元素,一是最靠右的那个数r(该数满足其左边存在比其大的数),二是最靠左的那个数i(该数满足其右边存在比其小的数)。寻找r的方法是:从左向右遍历,先寻找当前最大的并更新为maxx,然后一旦找到右边比maxx小的数,则更新r为i;寻找l的方法是:从右向左遍历,先寻找当前最小的并更新为minx,然后一旦找到左边比minx大的数,则更新l为i。其中l和r默认为-1,最后返回{l,r}即可。
vector<int> subSort(vector<int>& array)
{
//寻找最靠右的一个数(满足左边存在大于它的数)
//寻找最靠左的一个数(满足右边存在小于它的数)
int n=array.size();
int maxx=INT_MIN;
int minx=INT_MAX;
//默认l和r均为-1
int l=-1,r=-1;
//正向遍历寻找最靠右的一个数
for(int i=0;i<n;i++)
{
//左边寻找当前最大的 寻找右边比当前最大数小的
if(array[i]<maxx)
r=i;
else
maxx=array[i];
}
//反向遍历寻找最靠左的一个数
for(int i=n-1;i>=0;i--)
{
//右边寻找当前最小的 寻找左边比当前最小数大的
if(array[i]>minx)
l=i;
else
minx=array[i];
}
return {l,r};
}
总结:理解如何寻找最靠右的那个数r(该数满足其左边存在比其大的数)和最靠左的那个数i(该数满足其右边存在比其小的数)。