1. 程式人生 > >LeetCode 31 Medium 下一排列數 Python

LeetCode 31 Medium 下一排列數 Python

def nextPermutation(self, nums):
    """
    My Method
    演算法:指標+快排
    思路:
        首先要理解題意,這個有點頭疼,把題意理解後拆分成兩個部分就好做了。

        題目要求的是下一個更大的排列數,如果沒有下一個更大的排列數的話,就將序列升序排序
       [1,2,3,5,6,4,3] --> 1,2,{4,3,3,5,6}
        就是找到下一個更大的數
        所以我就從後向前,找到第一個出現拐點不是升序排序的兩個下標,即上面這個例子中的3和5,
        然後再從3往後的部分中找到最小的大於3的數字的下標,並且交換這兩個位置的值,那麼就是4
        所以我這裡有兩層while套著,第一層外面的while是去找到nums[l]<nums[r]的位置,第二層
        從l到len(nums-1)找到最小的大於nums[l]的數的下標min_max_index,然後交換l和min_max_index
        的值,退出
        此時的nums[l+1:]指向的就是待排的剩餘序列,用快排排序即可,並且如果整個序列是升序的,那麼退出while
        的條件就是l = -1,此時就是對l+1=0開始對整個陣列排序
        所以這個題其實就是兩個步驟:
            1.調整
            2.排序
    """
    if len(nums) < 2:
        return
    r = len(nums) - 1
    l = len(nums) - 2
    while l >= 0:
        if nums[l] >= nums[r]:
            r = l
            l -= 1
        elif nums[l] < nums[r]:
            min_max_index = len(nums) - 1
            while min_max_index > l:
                if nums[min_max_index] > nums[l]:
                    break
                min_max_index -= 1
            nums[l], nums[min_max_index] = nums[min_max_index], nums[l]
            break
    def partition(nums, lo, hi):
        if lo > hi:
            return
        pivot = nums[lo]
        l = lo
        r = hi
        while l < r:
            while l < r and nums[r] >= pivot:
                r -= 1
            nums[l] = nums[r]
            while l < r and nums[l] < pivot:
                l += 1
            nums[r] = nums[l]
        nums[l] = pivot
        return l

    def quick_sort(nums, lo, hi):
        if lo < hi:
            p = partition(nums, lo, hi)
            quick_sort(nums, lo, p - 1)
            quick_sort(nums, p + 1, hi)

    quick_sort(nums, l+1, len(nums) - 1)

def nextPermutation1(self, nums):
    """
    Solution Method
    演算法:指標+交換調整
    思路:
        整體來說和上面的 My Method一樣,不同的是這裡第二步排序的時候,利用了經過第一步調整後後序序列一定是
        降序排序的特徵進行調換元素的方式進行排序處理,比快排要快
        所以還是要根據題目特徵去調整的,不能簡單粗暴就上快排
    """
    if len(nums) < 2:
        return
    r = len(nums) - 1
    l = len(nums) - 2
    while l >= 0:
        if nums[l] >= nums[r]:
            r = l
            l -= 1
        elif nums[l] < nums[r]:
            min_max_index = len(nums) - 1
            while min_max_index > l:
                if nums[min_max_index] > nums[l]:
                    break
                min_max_index -= 1
            nums[l], nums[min_max_index] = nums[min_max_index], nums[l]
            break
    lo = l + 1
    hi = len(nums) - 1
    #swap
    while lo < hi:
        nums[lo], nums[hi] = nums[hi], nums[lo]
        lo += 1
        hi -= 1