1. 程式人生 > >581. Shortest Unsorted Continuous Subarray

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;
    }
}