全排列 | 下一个排列
字典序更大
字典序更大是指在字典序排列中,一个排列比另一个排列更大。字典序排列是按照元素从左到右的顺序进行比较的,类似于字典中单词的排列顺序。
具体来说,对于两个排列 ( a = [ a 1 , a 2 , … , a n ] ) (a = [a_1, a_2, \ldots, a_n]) (a=[a1,a2,…,an]) 和 ( b = [ b 1 , b 2 , … , b n ] ) (b = [b_1, b_2, \ldots, b_n]) (b=[b1,b2,…,bn]),我们从左到右逐个比较它们的元素:
- 如果存在某个位置 i 使得 ( a i > b i ) (a_i > b_i) (ai>bi),并且对于所有 ( j < i ) (j < i) (j<i),都有 ( a j = b j ) (a_j = b_j) (aj=bj),那么我们说排列 a a a 比排列 b b b 字典序更大。
- 如果所有位置的元素都相等,即 ( a i = b i ) (a_i = b_i) (ai=bi) 对于所有 i 都成立,那么我们说排列 a a a 和排列 b b b 相等。
所以,字典序更大意味着在字典序排列中,一个排列排在另一个排列的后面。在生成下一个排列时,我们需要找到字典序更大的下一个排列,即在所有排列的有序容器中排在当前排列后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列,即其元素按升序排列。
下一个排列
例子:
假设我们有一个排列 (a = [1, 3, 5, 4, 2])。
-
从右向左找到第一个升序对:(a[2] = 3) 和 (a[3] = 5) 是最后一个升序对,所以 (i = 2)。
-
在 (a[3] = 5, a[4] = 4, a[5] = 2) 中找到大于 (a[2] = 3) 的最小元素,是 (a[4] = 4),所以 (j = 4)。
-
交换 (a[2]) 和 (a[4]):得到排列 ([1, 4, 5, 3, 2])。
-
将 (a[3] = 5, a[4] = 3, a[5] = 2) 逆序:得到排列 ([1, 4, 2, 3, 5])。
所以,排列 ([1, 3, 5, 4, 2]) 的字典序下一个排列是 ([1, 4, 2, 3, 5])。
要生成一个排列的字典序下一个排列,我们可以按照以下步骤进行:
-
从右向左找到第一个升序对:找到排列中最后一个满足 (a[i] < a[i+1]) 的位置 (i)。如果这样的 (i) 不存在,说明排列已经是字典序最大的排列,下一个排列就是字典序最小的排列,即排列的逆序。
-
找到大于 (a[i]) 的最小元素:在 (a[i+1]) 到 (a[n-1]) 中找到大于 (a[i]) 的最小元素,假设其位置为 (j)。
-
交换 (a[i]) 和 (a[j]):将 (a[i]) 和 (a[j]) 交换。
-
将 (a[i+1]) 到 (a[n-1]) 逆序:将 (a[i+1]) 到 (a[n-1]) 的元素逆序,这样可以得到字典序最小的排列。
python实现
def nextP(index):
global s, n # 确保 s 和 n 在函数内部可用
for _ in range(index):
if n <= 1: # 如果排列长度小于等于1,直接返回
return
for i in range(n - 2, -1, -1): # 从倒数第二个元素开始遍历
if s[i] < s[i + 1]: # 找到第一个非递减的位置
for j in range(n - 1, i, -1): # 从后往前找第一个比 s[i] 大的数
if s[j] > s[i]:
s[i], s[j] = s[j], s[i] # 交换它们
s[i + 1:] = sorted(s[i + 1:]) # 让后面的部分变为升序
break
break
else:
s.sort() # 如果整个序列已经是最大排列,则直接变成最小排列
n = int(input().strip()) # n:表示序列的长度(即有多少个数)
index = int(input().strip()) # index:表示要执行 “求下一个排列” 的次数
s = list(map(int, input().split())) # 读取数组
nextP(index)
print(' '.join(map(str, s))) # 输出最终排列
参考
https://blog.csdn.net/m0_54689021/article/details/125573187