【搞定算法】需要排序的最短子數組長度

題目:給定一個無序數組 arr,求出需要排序的最短子數組長度。例如:arr = [1,5,3,4,2,6,7] 返回 4,因爲只有 [5,3,4,2] 需要排序。

要求:時間複雜度 O(N)、額外空間複雜度O(1)。

 假設數組爲 [a b c d e f g h i j k l m n],如果 abc 是有序的,mn是 有序的,至於中間的 defghijkl 是無序的,我們可以得知,如果是正常升序序列,左邊的一定是小於右邊的任意數值,右邊的一定大於左邊的任意數值。

分析:

分別從左往右和從右往左遍歷,找出左右兩邊失效的位置,則這兩個失效位置中間的數組即爲需要排序的最短子數組。

步驟:

1、從左向右遍歷,找出不合適數的最右範圍:從左往右遍歷,如果 maxLeft > 當前元素,則記錄它的位置到 invalidRight ,一直遍歷到最右邊【可知 invalidRight 是最後一個不滿足排序要求的數,其右邊都滿足大於 invalidRight 】

2、從右向左遍歷,找出不合適數的最左範圍:從右往左遍歷,如果當前元素 > minRight,則記錄它的位置爲 invalidLeft,一直遍歷到最左邊 【可知 invalidLeft 是最後一個不滿足排序要求的數,其左邊都滿足小於 minRight】

3、invalidRight - invalidLeft + 1 就是需要排序的最短子數組長度。 

public class GetMinLengthForSort {

    public static int getMinLengthForSort(int[] arr){
        if(arr == null || arr.length < 2){
            return 0;   // 不需要排序
        }

        int maxLeft = arr[0];  // 左邊最大
        int minRight = arr[arr.length - 1];  // 右邊最小
        // 這兩個指針分別記錄左右兩邊無效的位置
        int invalidLeft = 0;
        int invalidRight = -1;  // 數組原本有序時:invalidRight - invalidLeft + 1 = 0
        // 1、從左到右遍歷:找出不合適數的最右範圍
        // 遍歷過的最大值大於當前值,那麼當前值肯定是無效的,那麼排序時這個最大值在當前位置或者是更右的位置
        for(int i = 1; i < arr.length; i++){
            if(maxLeft > arr[i]){
                // 如果已經遍歷過的最大值大於當前值,則記錄最右邊無效位置
                invalidRight = i;
            }else{
                // 如果已經遍歷過的最大值小於等於當前值,則遍歷過的最大值更新爲當前值
                maxLeft = arr[i];
            }
        }
        // 2、從右向左遍歷:找出不合適數的最左範圍
        // 遍歷過的最小值小於當前值,那麼當前值就是無效的,那麼排序時這個最小值在當前位置或者是更左的位置
        for(int i = arr.length - 2; i >= 0; i--){
            if(minRight < arr[i]){
                // 如果已經遍歷的最小值小於當前值,則記錄最左邊無效的位置
                invalidLeft = i;
            }else{
                // 更新最小值
                minRight = arr[i];
            }
        }
        // invalidRight是不合適數的最右範圍,invalidLeft 是不合適數的最左範圍
        // invalidRight - invalidLeft + 1 就是不合適數的個數
        return invalidRight - invalidLeft + 1;
    }

    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        System.out.println(getMinLengthForSort(arr));
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章