【LeetCode】581. 最短的無排序連續子數組

問題描述

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.

Note:

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

給定一個整數數組,你需要找到一個連續的子數組,如果只按升序對這個子數組排序,那麼整個數組也將按升序排序。
你需要找到最短的子數組並輸出它的長度。

注意:
那麼輸入數組的長度在[1,10,000]範圍內。
輸入數組可能包含重複項,所以這裏升序表示<=。

輸入: [2, 6, 4, 8, 10, 9, 15]
輸出: 5

 

Python 實現

實現一:排序後再通過比較找出邊界。簡單粗暴的方法,直接上代碼。

class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        
        length = len(nums)
        if length <= 1:
            return 0

        arr = sorted(nums)
        length = len(nums)
        for i in range(length):
            if arr[i] != nums[i]:
                break
        for j in range(length, 0, -1):
            if arr[j-1] != nums[j-1]:
                break
        if j-1 < i:
            return 0
        else:
            return j-i

實現二:尋找左右兩個邊界。思路和冒泡排序法有點類似,但我們並不是真的進行排序。我們知道,冒泡排序法就是遍歷時將前後兩個元素進行對比,(假設是升序排序)較大值會被交換到靠後的位置。在這一道題目裏,我們不把較大值交換到靠後的位置,而是記錄這個最大值,並以之爲比較標準,位置靠後且小於該最大值的元素,必然是整個數組排序時需要考慮的部分,也就是我們所要求的最短無排序連續子數組的元素之一,因此我們記錄下最靠後的最小值的索引,即爲所求子數組的右邊界。同理,從右往左遍歷,相當於通過冒泡排序法排成降序的形式,我們記錄中間出現的最小值作爲比較對象,記錄最後出現的較大值的索引,即爲左邊界。

使用上述方法,最多需要遍歷兩次數組(前後各一次),需要4個變量來記錄最大值、最小值、左邊界、右邊界,因此時間複雜度爲 O(n),空間複雜度爲 O(1)。

class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        
        length = len(nums)
        if length <= 1:
            return 0
        
        left = right = -1
        maxEdge = nums[0]
        minEdge = nums[length-1]
        
        for i in range(1, length):
            maxEdge = max(maxEdge, nums[i])
            if maxEdge > nums[i]:
                right = i
        if right == -1:
            return 0
        
        for j in range(length-1, 0, -1):
            minEdge = min(nums[j-1], minEdge)
            if minEdge < nums[j-1]:
                left = j-1
            
        return right - left + 1
        

鏈接:https://leetcode.com/problems/shortest-unsorted-continuous-subarray/

 

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