雙周賽113。

題目

輸入長度n,由不同正整數組成的陣列nums。
求使得nums有序所需的最少右移次數,若不可能則回傳-1。

右移指的是將所有位於i的元素移動至(i+1)%n。

解法

數據範圍小,照常暴力解決。

對於長度n的陣列來說,只有n種有效的移動結果,也就是右移0~n-1次。
先找到nums排序後的結果,依次模擬nums右移,若等同於排序則回傳當前次數。

時間複雜度O(n^2)。
空間複雜度O(n)。

class Solution:
    def minimumRightShifts(self, nums: List[int]) -> int:
        N=len(nums)
        a=sorted(nums)
        
        if a==nums:
            return 0
        
        for i in range(1,N):
            t=nums.pop()
            nums=[t]+nums
            if nums==a:
                return i
            
        return -1

如果能透過右移使得nums有序,則代表他本來就是有序,只是先前被右移了數次。
這種情況下nums會形成兩段遞增的子陣列,例如[3,4] + [1,2]。

此外,右段的最後一個數不得大於左段的第一個數,否則整個陣列不可能有序。
例如[3,4] + [2,4]則不合規則。

同時符合以上兩點,右半的長度則等於需要右移的次數。

時間複雜度O(N)。
空間複雜度O(1)。

class Solution:
    def minimumRightShifts(self, nums: List[int]) -> int:
        N=len(nums)
        
        # find first increasing part
        i=0
        while i+1<N and nums[i]<=nums[i+1]:
            i+=1
        
        # already sorted
        if i==N-1:
            return 0
        
        # find second increasing part
        i+=1
        i0=i
        while i+1<N and nums[i]<=nums[i+1]:
            i+=1
        
        # more than 2 part
        if i!=N-1:
            return -1
        
        if nums[0]<nums[-1]:
            return -1

        # shift second part to front side
        # [i0, N-1]
        return N-1-i0+1