给定一个整数数组,你需要找出一个连续子数组,将这个子数组升序排列后整个数组都将是升序数组。
请你找出满足题设的最短的子数组。
数据范围:数组长度满足
, 数组中的元素满足 
[2,6,4,8,10,9,15]
5
只需对 6,4,8,10,9 排序即可得到升序数组
[1,2,3,5,4]
2
对 5,4 排序即可得到升序数组
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int findUnsortedSubarray (int[] nums) {
// write code here
int n = nums.length;
int[] rawNums = Arrays.copyOfRange(nums, 0, n);
Arrays.sort(nums);
int left = 0, right = n - 1;
while(left < n && rawNums[left] == nums[left]){
left++;
}
while(right >= 0 && rawNums[right] == nums[right]){
right--;
}
return Math.max(right - left + 1, 0);
}
} 排序的时间复杂度为O(nlogn),后面双指针的时间复杂度为O(n),整体的时间复杂度为O(nlogn)。拷贝了原始数组,所以额外空间复杂度为O(n)。 class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型
*/
int findUnsortedSubarray(vector<int>& nums) {
int n = nums.size();
int leftMax = nums[0], rightMin = nums[n - 1], l = -1, r = -2;
for(int i = 1; i < n; i++){
leftMax = max(leftMax, nums[i]); // nums[0:i]的最大值
rightMin = min(rightMin, nums[n - 1 - i]); // nums[n-1-i:n-1]的最小值
if(leftMax != nums[i]){
r = i;
}
if(rightMin != nums[n - 1 - i]){
l = n - 1 - i;
}
}
return r - l + 1;
}
}; 只遍历了一遍数组,时间复杂度为O(n)。只使用了有限几个变量,空间复杂度为O(1)。 public static int findUnsortedSubarray(int[] nums) {
int[] nums2 = Arrays.copyOfRange(nums, 0, nums.length);
Arrays.sort(nums);
int left = nums.length - 1, right = 0;
boolean isLeft = true, isRight = true;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != nums2[i] && isLeft) {
left = i;
isLeft = false;
}
if (nums[nums.length - i - 1] != nums2[nums2.length - 1 - i] && isRight) {
right = nums.length - i - 1;
isRight = false;
}
}
return right <= left ? 0 : right - left + 1;
} 总结:需要排序和拷贝原数据,时间复杂度和空间复杂度略高 public static int findUnsortedSubarray(int[] nums) {
int n = nums.length;
int l = n - 1, r = 0;
int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
for (int i = 1; i < n; i++) {
// 确认右边界 r
if (nums[i] < max)
r = i;
// 更新 max
max = Math.max(max, nums[i]);
// 确认左边界 l
if (nums[n - 1 - i] > min)
l = n - 1 - i;
// 更新 min
min = Math.min(min, nums[n - 1 - i]);
}
return r > l ? r - l + 1 : 0;
} public static int findUnsortedSubarray(int[] nums) {
Stack<Integer> monoStack = new Stack<>();
Stack<Integer> helper = new Stack<>();
int left = nums.length - 1, right = 0;
for (int i = 0; i < nums.length; i++) {
if (monoStack.isEmpty()) {
monoStack.push(i);
} else {
// 构建单调栈
while (!monoStack.isEmpty() && nums[monoStack.peek()] > nums[i]) {
// 找到所有比 nums[i] 要大的下标,取最小即为左边界
left = Math.min(left, monoStack.peek());
helper.push(monoStack.pop());
right = i; // 当发现乱序的时候,i 代表当前乱序的最大下标
}
monoStack.push(i);
while (!helper.isEmpty()) monoStack.push(helper.pop());
}
}
return right <= left ? 0 : right - left + 1;
} 说明:这种方法需要用到辅助栈,并且对于乱序程序较大的数组如 [100,99,......,3,2,1],会更加频繁地出栈入栈,时间复杂度较高, 空间复杂度也较高, 稳定性较差public static int findUnsortedSubarray(int[] nums) {
Stack<Integer> monoStack = new Stack<>();
int left = nums.length - 1, right = 0, max = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
if (!monoStack.isEmpty()) {
// 构建单调栈,找到乱序的元素最大下标 i
while (!monoStack.isEmpty() && nums[monoStack.peek()] > nums[i]) {
// 找到最小的不乱序的下标就是左边界
left = Math.min(left, monoStack.pop());
}
// 当前元素只要小于历史最大值,当前下标就是右边界
max = Math.max(max, nums[i]);
if (nums[i] < max) right = i;
}
monoStack.push(i);
}
return right <= left ? 0 : right - left + 1;
} class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型
*/
int findUnsortedSubarray(vector<int>& nums) {
// write code here
vector<int> tmp;
for(int i=0; i<nums.size(); i++)
tmp.push_back(nums[i]);
sort(tmp.begin(), tmp.end());
int left =0, right = 0;
for(int i=0; i<nums.size(); i++)
{
if(nums[i] != tmp[i])
{
left = i;
break;
}
}
for(int i=nums.size()-1; i>=0; i--)
{
if(nums[i] != tmp[i])
{
right = i;
break;
}
}
if(left == 0 && right == 0)
return 0;
return right - left + 1;
}
}; package main
import _"fmt"
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
func findUnsortedSubarray( nums []int ) int {
n:=len(nums)
if n<2{
return 0
}
max,min:=0,n-1
ans:=[]int{0,n-1}
for l,r:=1,n-2;l<n&&r>=0;l,r=l+1,r-1{
if nums[l]<nums[max]{
ans[0]=l
}else{
max=l
}
if nums[r]>nums[min]{
ans[1]=r
}else{
min=r
}
}
if ans[0]<ans[1]{
return 0
}
return ans[0]-ans[1]+1
}
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int findUnsortedSubarray (int[] nums) {
// write code here
Stack<Integer> stack = new Stack<>();
int start = Integer.MAX_VALUE;
int end = Integer.MAX_VALUE - 1;
int curMaxNum = 0;
for(int i = 0; i < nums.length; i++){
while(!stack.isEmpty() && nums[stack.peek()] > nums[i]){
int startTemp = stack.pop();
start = Math.min(start, startTemp);
}
// 更新最大值
curMaxNum = Math.max(curMaxNum, nums[i]);
// 如果当前不是最大值,则end 更新到当前位置
if(curMaxNum != nums[i]){
end = i;
}
stack.push(i);
}
return end - start + 1;
}
} 暴力
import java.util.*;
public class Solution {
public int findUnsortedSubarray (int[] nums) {
// write code here
int start = -1;
int end = 0;
for(int i = 0 ;i<nums.length;i++){
for(int j = nums.length-1 ;j>i;j--){
if(nums[j]<=nums[i]){
end = j;//最后边的逆序对的终点
if(start==-1){
start = i;//第一个逆序对的起点
}
break;
}
}
}
if(start == -1) return 0;
return end - start + 1;
}
}