Sub Sort:在整数序列中求出一个最短区间[m, n]
,满足将该区间内的数据升序排序后,整个序列都升序。
根据题意,如果对[m, n]
之间的数据进行排序就可以使整个序列有序,那么区间[0, m)
和下标大于n
的数据都应该是有序的,所以应该先找出开头和结尾的升序序列。
这样序列就分为了3
部分,left
、middle
和right
,m
或者middle
中第一个元素的下标,或者是left
中的某一个元素的下标,所以应该在middle
和right
中找出一个最小值,如果left
中有元素比它大,那么就找到了m
。
对于n
,m
或者middle
中最后一个元素的下标,或者是right
中的某一个元素的下标,所以应该在left
和middle
中找出一个最大值,如果right
中有元素比它小,那么就找到了n
。
class Solution {
public:
vector<int> subSort(vector<int>& vec) {
if(vec.empty()) return {-1, -1};
size_t b = 1, e = vec.size() - 1;
while(b < vec.size()){
if(vec[b - 1] > vec[b]) break;
else b++;
}
while(e > 1){
if(vec[e] < vec[e - 1]) break;
else e--;
}
if(b > e) return {-1, -1};
size_t minIdx = b, maxIdx = e - 1;
for(size_t i = b; i < vec.size(); i++)
{
if(vec[i] <= vec[minIdx]) minIdx = i;
}
for(size_t j = e; j > 0; j--)
{
if(vec[j - 1] >= vec[maxIdx]) maxIdx = j - 1;
}
int left = b, right = e - 1;
for(size_t i = 0; i < b; i++)
{
if(vec[i] > vec[minIdx]){
left = i;
break;
}
}
for(size_t j = vec.size(); j > e; j--)
{
if(vec[j - 1] < vec[maxIdx]){
right = j - 1;
break;
}
}
return {left, right};
}
};
上一个版本中使用下标太难理解了,所以又用反向迭代器重写了一遍,和正向迭代器的代码完全对称,非常容易理解。
class Solution {
public:
vector<int> subSort(vector<int>& vec) {
if(vec.empty()) return {-1, -1};
vector<int>::iterator b = vec.begin() + 1;
vector<int>::reverse_iterator e = vec.rbegin() + 1;
while(b != vec.end()){
if(*b < *(b - 1)) break;
else b++;
}
while(e != vec.rend()){
if(*e > *(e - 1)) break;
else e++;
}
if(b > e.base()) return {-1, -1};
auto min = b;
auto max = e;
for(auto i = b; i != vec.end(); i++)
{
if(*i <= *min) min = i;
}
for(auto ri = e; ri != vec.rend(); ri++)
{
if(*ri >= *max) max = ri;
}
int left = -1, right = -1;
for(auto i = vec.begin(); i != b; i++)
{
if(*i > *min){
left = i - vec.begin();
break;
}
}
for(auto ri = vec.rbegin(); ri != e; ri++)
{
if(*ri < *max){
right = ri.base() - vec.begin() - 1;
break;
}
}
return {left, right};
}
};