寻找全排列的下一个数(Python)

一、题目描述
给出一个数,找出这个正整数所有数字全排列的下一个数。
即:在一个整数所包含数字的全部组合中,找到一个大于且仅大于原数的新整数。
如:
如果输入12345,则返回12354;
如果输入12354,则返回12435

二、解题思路
首先当这5个数字逆序组合时最大:54321;顺序组合时最小:12345
为了得到比原数稍大的下一个数,我们需要尽量保持高位不变,低位在最小的范围内变换顺序
至于变换顺序的范围大小,则取决于当前整数的逆序区域
比如:12354,要想获得比它大的下一个数,则需要从倒数第三位开始改变。首先从后面的逆序区域中找到大于3的最小数字,让其和3的位置进行互换。然后,需要把最后两位变成顺序状态,让后两位尽可能的小。

总结来说:获得全排列的下一个数需要三个步骤:
1、从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界。
2、让逆序区域的前一位和逆序区域中大于它的最小的数字交换位置。
3、让原来的逆序区域变成顺序状态。

代码实现:

def find_nearest_number(numbers=[]):
    # 1、从后向前查看逆序区域,找到逆序区域的最后一位
    index=find_transfer_point(numbers)
    # 如果数字置换的边界是0,说明整个数组已经逆序,无法得到更大的数字,返回null
    if index==0:
        return None
    # 2、把逆序区域的前一位和逆序区域中刚刚大于它的数字进行交换
    # 复制入参,避免直接修改入参
    numbers_copy=numbers.copy()
    exchange_head(index,numbers_copy)
    # 3、把原来的逆序区域变为顺序
    reverse(index,numbers_copy)
    return numbers_copy



def find_transfer_point(numbers=[]):
    for i in range(len(numbers)-1,0,-1):
        if numbers[i]>numbers[i-1]:
            return i
    return 0

def exchange_head(index,numbers=[]):
    head=numbers[index-1]
    for i in range(len(numbers)-1,0,-1):
        # 因为后续数据是逆序的,遇到第一个大于head的,肯定就是所有大于它的数据中最小的一个
        if head<numbers[i]:
            numbers[index-1]=numbers[i]
            numbers[i]=head
            break
    return numbers

def reverse(index,numbers=[]):
    i=index
    j=len(numbers)-1
    while i<j:
        numbers[i],numbers[j]=numbers[j],numbers[i]
        i += 1
        j -= 1
    return numbers

def output_numbers(numbers=[]):
    for i in numbers:
        print(i,end="")
    print()

my_numbers=list([1,2,6,3,5,4])
output_numbers(find_nearest_number(my_numbers))

寻找全排列的下一个数(Python)_第1张图片

你可能感兴趣的:(笔面试试题)