Next Permutation in Lexicographic Order

def next_permutation(arr):
    # Step 1: Find the longest non-increasing suffix
    i = len(arr) - 2
    while i >= 0 and arr[i] >= arr[i + 1]:
        i -= 1
    
    # Step 2: If the entire array is non-increasing, reverse it
    if i == -1:
        arr.reverse()
        return arr
 
    # Step 3: Find the smallest element in the suffix larger than arr[i]
    j = len(arr) - 1
    while arr[j] <= arr[i]:
        j -= 1
 
    # Step 4: Swap elements at i and j
    arr[i], arr[j] = arr[j], arr[i]
 
    # Step 5: Reverse the suffix starting at i+1
    arr[i + 1:] = reversed(arr[i + 1:])
    
    return arr

For example, if we want to generate the permutations of . First we find the longest non-increasing suffix (with least length ). That is . The smallest element in the suffix larger than is , then we swap and reverse the elements after (that is itself). Then we get

Now the longest non-increasing suffix is . The smallest element in the suffix larger than is , then we swap and we get . Afterwards we reverse the elements , and we get

Next Combination in Lexicographic Order

def next_combination(arr, n, k):
    # Step 1: Find the rightmost element that can be incremented
    i = k - 1
    while i >= 0 and arr[i] == n - k + i:
        i -= 1
 
    # Step 2: If no such element exists, the current combination is the last one
    if i < 0:
        return None
 
    # Step 3: Increment this element
    arr[i] += 1
 
    # Step 4: Set all elements to the right to the smallest values possible
    for j in range(i + 1, k):
        arr[j] = arr[i] + j - i
    
    return arr

For example, if we want to find the next -combination of after . The rightmost element that can be incremented is , so we get . Then we need to set all the elements to the right to the smallest values possible, that is