1. 程式人生 > >LeetCode31:Next Permutation

LeetCode31:Next Permutation

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place and use only constant extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1


LeetCode:連結

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l such that a[k] < a[l]. Since k+1 is such an index, l is well defined and satisfies k < l.
  3. Swap a[k] with a[l].
  4. Reverse the sequence from a[k+1] up to and including the last element a[n].

第一步找出一個k,使得k之後的為遞減序列。(k之後的就沒有全排列的結果了。想一下4321這種,都是逆序的)

接下來,我們需要找到一個最大的下標L使得 a[k]<a[L],交換a[k]和a[L] (就是說遞減序列中比a[k]大的最小的元素, 這樣和位置k的進行交換,位置k之後的就又有全排列了)

最後對k+1之後的逆置即可,這樣就變成了升序。

eg: 1 4 3  2  k=0 L=3  swap-> 2431 逆置-> 2134

class Solution(object):
    def sort(self, nums):
        start = 0
        end = len(nums) - 1
        self.partition(nums, start, end)
        return nums

    def partition(self, nums, start, end):
        if end <= start:
            return start
        index1, index2 = start, end
        base = nums[start]
        while start < end:
            while start < end and nums[end] >= base:
                end -= 1
            nums[start] = nums[end]
            while start < end and nums[start] <= base:
                start += 1
            nums[end] = nums[start]
        nums[start] = base
        self.partition(nums, index1, start-1)
        self.partition(nums, start+1, index2)

    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        i = len(nums) - 2
        # 由於下一個數比上一個數大,因此需要從後往前掃描,找到遞增的位置設為元素i
        while i >= 0:
            if nums[i] < nums[i+1]:
                break
            i -= 1
        # 找不到,則將全部元素遞增排序
        if i == -1:
            nums = self.sort(nums)
        j = len(nums) - 1
        while j > i:
            if nums[j] > nums[i]:
                '''接下來,我們需要找到一個最大的下標j使得a[i]<a[j],交換a[i]和a[j]
                就是說遞減序列中比a[i]大的最小的元素, 這樣和位置i的進行交換,位置i之後的就又有全排列了
                '''
                nums[i], nums[j] = nums[j], nums[i]
                # 最後對i+1之後的逆置即可,這樣就變成了升序。
                nums[i+1:] = nums[i+1:][::-1]
                break
            j -= 1