581. Shortest Unsorted Continuous Subarray

题目:

Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too.

You need to find the shortest such subarray and output its length.

Example 1: Input: [2, 6, 4, 8, 10, 9, 15] Output: 5 Explanation:
You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole
array sorted in ascending order.

Note:
Then length of the input array is in range [1, 10,000].
The input array may contain duplicates, so ascending order here means <=.

翻译过来就是:

给定一个整数数组,你需要找到一个连续的子数组,如果你只按升序对这个子数组排序,那么整个数组也将按照升序排序。

你需要找到最短的这样的子数组并输出它的长度。

例1:
输入: [2,6,4,8,10,9,15]
 输出: 5
 说明:您需要按升序对[6,4,8,10,9]进行排序,以使整个数组按升序排序。
注意:
然后输入数组的长度在[1,10,000]范围内。
输入数组可能包含重复项,因此这里的升序表示<=。

  刚开始的时候是想从两边分别开始,(通过循环,进行两两对比)从前往后找(目标数组是升序排列)下一个比这个小的数,以及从后往前找前一个比这个大的数,用两个数分别记住他俩的下标,然后做差加一。
  但是写出来之后发现一个问题,例如[5,6,1,2,3,4,7,8]这样的数组在从后往前比较的时候,被标记的元素的下标是2,而不是5。
  所以改变思路,先将数组拷贝出来,然后排序。接着将排完序的数组与原数组 进行相同位置的元素进行比较。当发现不同的时候,将其位置下标进行标记即可,最后将标记出来的两个下标做差加一即可。

下面附上代码,以及一个代码量稍小一点的方法二(其思路和前面的差不多)

//法二:
//    目标是从大到小排列,从两头开始找,对于有序的部分掠过,对于不在顺序之中的部分下标标记。
//class Solution1 {
//    public int findUnsortedSubarray(int[] nums) {
//        int n=nums.length,beg =-1,end=-2,mn=nums[n-1],mx=nums[0];
//        for(int i=1;i<n;i++){
//            mx=Math.max(mx,nums[i]);
//            mn = Math.min(mn, nums[n-1-i]);
//            if (nums[i]<mx) end=i;
//            if(nums[n-1-i]>mn) beg=n-1-i;
//        }
//        return end-beg+1;
//    }
//}

//法一:
//目标是从小到大排列,先将数组拷贝之后排序,然后把有序数组与原数组 相同位置进行比较,
// 同一个位置 值不同的话,则说明该位置无须,需要标记
class Solution1 {
    public int findUnsortedSubarray(int[] nums) {
//        拷贝数组,并将数组复制
        int[] copy = new int[nums.length];
        copy = (int[]) nums.clone();

//        数组排序
        Arrays.sort(copy);

//        从两头分别找出与排序好的元素值不同的元素下标
        int start=0, end=nums.length-1;
        for (; start < nums.length; start++) {
            if (nums[start]!=copy[start])   break;
        }
        for (; end >start; end--) {
            if (nums[end]!=copy[end])   break;
        }
        return end-start+1;
    }
}
点赞