LeetCode——581. 最短无序连续子数组[Shortest Unsorted Continuous Subarray][中等]——分析及代码[Java]
一、题目
给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
示例 1:
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
示例 2:
输入:nums = [1,2,3,4]
输出:0
示例 3:
输入:nums = [1]
输出:0
提示:
- 1 <= nums.length <= 10^4
- -10^5 <= nums[i] <= 10^5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. 二次遍历
(1)思路
假设题中最短子数组存在且范围为 [left, right],则在原数组中,[0, left) 区间内的所有元素大小均不超过目标区间内的元素,(right, n -1] 区间内的所有元素则均不小于目标区间。
根据这一特点,可从右向左遍历原数组,若当前数字已大于右侧所有数字中的最小值,则它可作为左边界,并可根据最终得到的左边界位置判断目标子数组是否存在。
用同样方法,可从左向右遍历得到右边界,从而输出目标子数组的长度。
(2)代码
class Solution {
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;//数组长度
//求符合题意的最短子数组的左边界
int left = n - 1, minNum = nums[n - 1];//当前左边界,已遍历到的最小值
for (int i = n - 2; i >= 0; i--) {//从右向左遍历
if (nums[i] > minNum)//当前数字已大于最小值,可作为左边界
left = i;
else//当前数字不超过最小值,更新最小值
minNum = nums[i];
}
if (left == n - 1)//判断符合题意的最短无序连续子数组是否存在
return 0;
//求符合题意的最短子数组的右边界
int right = 0, maxNum = nums[0];//当前右边界,已遍历到的最大值
for (int i = 1; i < n; i++) {//从左向右遍历
if (nums[i] < maxNum)//当前数字已小于最大值,可作为右边界
right = i;
else//当前数字不超过最大值,更新最大值
maxNum = nums[i];
}
return right - left + 1;//输出目标子数组的长度
}
}
(3)结果
执行用时 :1 ms,在所有 Java 提交中击败了 100.00% 的用户;
内存消耗 :39.4 MB,在所有 Java 提交中击败了 79.37% 的用户。
三、其他
暂无。