Link
https://leetcode-cn.com/problems/next-permutation/
Solution
参考来自:https://blog.csdn.net/QQ575787460/article/details/41215475
在当前序列中,从尾端往前寻找两个相邻元素,前一个记为 *i ,后一个记为 *ii ,并且满足 *i < *ii 。然后再从尾端寻找另一个元素 *j ,如果满足 *i < *j ,即将第 i 个元素与第 j 个元素对调,并将第 ii 个元素之后(包括 ii )的所有元素颠倒排序,即求出下一个序列了。
首先,关于什么是全排列不做解释。如果一个排列为 A ,下一个排列为 A_NEXT ,那么 A_NEXT 一定与 A 有尽可能长的公共前缀。
看具体例子,一个排列为 124653 ,如何找到它的下一个排列,因为下一个排列一定与 124653 有尽可能长的前缀,所以,脑洞大开一下,从后面往前看这个序列,如果后面的若干个数字有下一个排列,问题就得到了解决。
第一步:找最后面 1 个数字的下一个全排列。
124653,显然最后 1 个数字 3 不具有下一个全排列。
第二步:找最后面 2 个数字的下一个全排列。
124653,显然最后 2 个数字 53 不具有下一个全排列。
第三步:找最后面 3 个数字的下一个全排列。
124653,显然最后 3 个数字 653 不具有下一个全排列。
——插曲:到这里相信大家已经看出来, 如果一个序列是递减的,那么它不具有下一个排列。
第四步:找最后面4个数字的下一个全排列。
124653,我们发现显然最后 4 个数字 4653 具有下一个全排列。因为它不是递减的,例如 6453 , 5643 这些排列都在 4653 的后面。
我们总结上面的操作,并总结出重复上面操作的两种终止情况:
1:从后向前比较相邻的两个元素,直到前一个元素小于后一个元素,停止
2:如果已经没有了前一个元素,则说明这个排列是递减的,所以这个排列是没有下一个排列的。
124653 这个排列终止情况是上面介绍的第一种,从后向前比较相邻的 2 个元素,遇到 4<6 的情况停止。
并且我们可以知道:
1:124653 和它的下一个排列的公共前缀为 12 (因为 4653 存在下一个排列,所以前面的数字 12 保持不变)
2:4 后面的元素是递减的(上面介绍的终止条件是前一个元素小于后一个元素,这里是 4<6 )
现在,我们开始考虑如何找到4653的下个排列,首先明确4后面的几个数字中至少有一个大于4.
4 肯定要和 653 这 3 个数字中大于 4 的数字中 (6,5) 的某一个进行交换。这里就是 4 要和 6 , 5 中的某一个交换,很明显要和 5 交换,如果找到这样的元素呢,因为我们知道 4 后面的元素是递减的,所以在 653 中从后面往前查找,找到第一个大于4的数字,这就是需要和4进行交换的数字。这里我们找到了 5 ,交换之后得到的临时序列为 5643 ,交换后得到的 643 也是一个递减序列。
所以得到的 4653 的下一个临时序列为 5643 ,但是既然前面数字变大了(4653—>5643),后面的自然要变为升序才行,变换 5643 得到 5346 .
所以 124653 的下一个序列为 125643 .
Code
1 | class Solution { |