题目描述
给定一个整数数组,编写一个函数,找出索引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
解题思路
我们可以首先从左往右找右边界,记录已处理区间中的最大值,如果在后续遍历过程中找到一个值比最大值小,说明此时出现了前大后小的情况,说明该位置是需要排序的,更新 n
等于当前下标,这样一次扫描后就确定了右边界 n
。 同理可以从右往左找左边界,初始化 m = len-1
(len
为输入数组长度),记录已处理区间中的最小值, 如果找到一个值比最小值大,说明此时出现了前大后小的情况,说明该位置是需要排序的,则更新左边界 m
为该下标,这样一次扫描就确定了左边界 m
。
如此我们通过两次遍历数组就确定了 m
和 n
,最后判断 [m,n]
是否合法,如果合法,返回 [m,n]
,否则返回 [-1,-1
。
动画演示
代码实现
var subSort = function(array) {
let r = -1, l = -1; //两个指针记录一个升序,一个降序
// 从左往右找最右边的区间值
let max = Number.MIN_SAFE_INTEGER;
// 第一次排序从小到大
for(let i = 0; i < array.length; i++){
if(array[i] >= max){
max = array[i];
}else{
r = i;
}
}
// 从右往左找,找最左边的区间值
let min = Number.MAX_SAFE_INTEGER;
for(let i = array.length - 1; i >= 0; i--){
if(array[i] <= min){
min = array[i];
}else{
l = i;
}
}
return [l , r];
};
复制代码
至此我们就完成了leetcode-面试题 16.16-部分排序