携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 21 天,点击查看活动详情
部分排序
原题地址
给定一个整数数组,编写一个函数,找出索引m和n,只要将索引区间[m,n]
的元素排好序,整个数组就是有序的。注意:n-m
尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n]
,若不存在这样的m和n(例如整个数组是有序的),请返回[-1,-1]
。
示例1:
输入: [1,2,4,7,10,11,7,12,6,7,16,18,19]
输出: [3, 9]
示例2:
输入: [5,3,1,7,9]
输出: [0, 2]
提示:
0 <= len(array) <= 1000000
思路分析
方法一
- 分析题目,需要得到一个下标数组,满足只要将 这个区间内的数据进行排序,那么整个数组就是有序的;
- 根据题目可以得知,要寻找的
m
值是存在一个在这个位置后有一个值比array[m]
小的数值,而要寻找的n
值是存在一个在这个位置前有一个值比array[n]
大的数值; - 那么,可以定义一个
m
和n
,用来存储满足上述条件的所有下标; - 由于
m
是正向循环找到的,n
是逆向循环找到的满足条件的值的集合,那么第一个即为我们想要的结果; - 又因为若不存在时需要返回
-1
,那么在寻找结束后,在m
和n
中分别追加一个-1
,这样在找不到的时候有默认值; - 最后返回
[m[0], n[0]]
即可。
方法二
- 题目要求默认值为
-1
,那么定义m
和n
的初始值时,就定义为-1
; - 若存在这样一个区间,那么一定位于数组的中间,所以可以从左右两边来寻找这样的数据;
- 所以进行两次循环,分别找出左右两边的第一个逆序数,也就是左边找一个右侧有比它小的数值,右边找一个左侧有比它大的数值。找到返回即可。
AC 代码
方法一
/**
* @param {number[]} array
* @return {number[]}
*/
var subSort = function(array) {
let m = []
let n = []
for(let i = 0; i < array.length; i++) {
for(let j = i + 1; j < array.length; j++) {
if(array[j] < array[i]) {
m.push(i)
break
}
}
}
for(let i = array.length - 1; i >= 0; i--) {
for(let j = i - 1; j >= 0; j--) {
if(array[j] > array[i]) {
n.push(i)
break
}
}
}
m.push(-1)
n.push(-1)
return [m[0], n[0]]
};
结果:
- 执行结果: 通过
- 执行用时:5960 ms, 在所有 JavaScript 提交中击败了5.10%的用户
- 内存消耗:57.5 MB, 在所有 JavaScript 提交中击败了8.16%的用户
- 通过测试用例:38 / 38
方法二
/**
* @param {number[]} array
* @return {number[]}
*/
var subSort = function(array) {
let m = -1
let n = -1
let max = Number.MIN_SAFE_INTEGER
let min = Number.MAX_SAFE_INTEGER
for(let i = 0; i < array.length; i++){
if(array[i] >= max) max = array[i]
else n = i
}
for(let i = array.length -1; i >= 0; i--){
if(array[i] <= min) min = array[i]
else m = i
}
return [m, n]
};
结果:
- 执行结果: 通过
- 执行用时:60 ms, 在所有 JavaScript 提交中击败了96.94%的用户
- 内存消耗:49.3 MB, 在所有 JavaScript 提交中击败了57.14%的用户
- 通过测试用例:38 / 38