最短无序连续子数组的思路探讨与源码
最短无序连续子数组的题目如下图,该题属于数组和排序类型的题目,主要考察对于数组本身和排序方法的使用和理解。本文的题目作者想到2种方法,分别是排序方法和区间单遍历方法,其中排序方法使用java进行编写,而区间单遍历方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
本人认为该题目可以使用排序的方法,首先获取数组的长度进行判断,如果是小于2的数组则直接返回0的结果即可,然后使用遍历先对数组进行一次遍历判断,如果数组本身就是有顺序的,那就直接返回0的结果就行了。然后开始将原来的数组赋值拷贝为另一个数组,把拷贝以后的数组进行排序,然后从数组的两端开始与排序后的数组进行元素值的比较,找到数组的两边的第一个不相同的数字,然后计算下标之间的差值并加1以后,就是最短的子数组的长度。那么按照这个思路我们的Java代码如下:
#喷火龙与水箭龟
class Solution {
public int findUnsortedSubarray(int[] nums) {
int numLen = nums.length;
if (numLen == 0 || numLen == 1){
return 0;
}
if (sortFun(nums)) {
return 0;
}
int[] arrSort = new int[numLen];
System.arraycopy(nums,0,arrSort,0,numLen);
Arrays.sort(arrSort);
int begin = 0;
while (arrSort[begin] == nums[begin]) {
begin=begin+1;
}
int end = numLen - 1;
while (arrSort[end] == nums[end]) {
end=end-1;
}
int count = end - begin + 1;
return count;
}
public boolean sortFun(int[] arr) {
for (int ir = 1; ir < arr.length; ir++) {
if (arr[ir] < arr[ir - 1]) {
return false;
}
}
return true;
}
}
显然,我们看到排序方法的效率比较一般,所以还可以使用单次遍历的方法进行处理,这种方法其实是利用了有序数组内部的元素单调性的特性。首先对数组的长度进行判断,如果小于2则直接返回0的结果。然后将各个参数进行初始化,开始遍历数组,如果元素比最大值要小则将元素的下标赋值给右边的区间下标,反之则将元素的值赋值给最大值;如果当前区间的右下标,也就是根据数组长度减去当前下标后再减1的下标,它的值如果比最小值要大的话,那么就将右边的下标赋值给区间的左下标,反之则将右边下标对应的元素赋值给最小值。如果最终右下标是初始值那么就返回0,反之则返回区间左右下标的差值再加1的结果,也就是区间长度。所以按照这个思路就可以解决,下面是Python代码部分:
#喷火龙与水箭龟
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
numLen = len(nums)
if(numLen==0 or numLen==1):
return 0
maxNum = float("-inf")
minNum = float("inf")
begin = -1
end = -1
for jr in range(numLen):
if(maxNum > nums[jr]):
end = jr
else:
maxNum = nums[jr]
if(minNum < nums[numLen - jr - 1]):
begin = numLen - jr - 1
else:
minNum = nums[numLen - jr - 1]
if(end == -1):
return 0
else:
count = end - begin + 1
return count
从结果来说java版本的排序方法的效率比较一般,而python版本的单次遍历方法的速度也不是特别快,但应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。