LeetCode_Next Permutation
Posted rotk2015
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode_Next Permutation相关的知识,希望对你有一定的参考价值。
-
字典序全排列问题,该系列的核心问题是,如何从一个字典序的排列生成下一个最小排列。例如,12543 的下一个最小排列是,13245。
-
我们可以这么考虑,排列从左到右的每个数位,对应不同的权重。其中,最左边的权重最大,最右的权重最小(右至左如同个、十、百、千…);而给定的数字,如同砝码。那么这个问题翻译过来就是,生成下一个总重量大于当前重量的排列,且该排列在所有可能的结果中,总重量最小(说白了就是重一点意思一下得了)。
-
那么,给定数字 1 2 3 4 5,它的所有排列中,最小的、最大的分别是什么?这个问题很简单,我们要求最小的,只要让小砝码在大权重上,大砝码在小权重上就行了;要求最大的,那就反过来,大砝码在大权重上,小砝码在小权重上(这是整个算法的核心!)。
-
考虑刚刚举的例子,凭什么 12543 的下一个最小排列就是 13245 呢?我们是如何从 12543 演变到 13245 的呢?
-
注意到,12543 的后半段 543 是递减的。这意味着,在前两位 1 2 不动的前提下,后三位 3 4 5 已经取到了最大值 543,要再增加总重量,就得往前引入一个新的砝码了(老人都到极限了,要拉新人下水)。那么,拉谁呢?选 1 的话,2 就会占最高位;选 2 的话,1就会占最高位。显然选后者,因为我们只想重一点,按照第3条中的思想,要让大砝码在小权重上折腾,才能整体最小,所以我们拉 2 下水。
-
好的,现在我们将 1 扔到一边去不管他,考虑如何从 2543 演变至它的下一全排列。首先,2 肯定不能在最高位了,别忘了,2 在最高位的情况下,543 已经是最大值了,而我们要求下一个的总重量要更重,所以,我们拉 2 下水之后,还要安排一个比它更重的人顶它的位置。那么,我们选谁上位呢?由于后三位必是递减趋势(原因参照第5条,极限),所以我们从后往前数,找到第一个比 2 大的数(必定存在(除非是边界),且必定是比 2 大的数中最小的),3。这么做的原因参照第5条,我们只想重一点。
-
好了,现在 3 顶替了2上位,那么,2 该安排到哪里呢?考虑 3 上位前,是老人中的最小值,且已经在它所能在的最低位,它右边的数,没有比 2 更重的。所以,我们先让 2 待在 3 原来的位置,其他数保持原位不动,那么我们会获得一个比原来的 543 轻一点的配置:542,但这已经是 2 4 5 的极限了。下一步,由于 13 已经保证比 12 高了(且只是高一点),那么,我们只需保证让剩下的是最轻的配置,做法很简单,将新官 3 后边的数,全部逆序,即可得 245。最终拼接一下,得到 13245。
-
总结一下,算法分三步:
- 从右至左找到第一个元素 arr[i],使得 arr[i] < arr[i+1]。(对应第5条)
- 从右至左找到第一个元素 arr[j],使得 arr[i] < arr[j]。交换两者。(对应第6条,以及第7条的前半部分)
- 将从arr[i+1]到最右端的所有元素逆序。(对应第7条的后半部分)
-
代码如下:
import java.util.ArrayList; import java.util.Arrays; public class Solution public ArrayList<String> Permutation(String str) ArrayList<String> lis = new ArrayList<>(); if(str==null || str.length()==0) return lis; char[] cArr = str.toCharArray(); Arrays.sort(cArr); lis.add(new String(cArr)); helper(cArr, lis); return lis; private void helper(char[] arr, ArrayList<String> lis) int len = arr.length; int i = len-2; for(; i>=0 && arr[i]>=arr[i+1]; i--); if(i<0) return; int j = len-1; for(; j>=0 && arr[i]>=arr[j]; j--); swap(arr, i, j); for(int lef=i+1, rig=len-1; lef<rig; lef++, rig--) swap(arr, lef, rig); lis.add(new String(arr)); helper(arr, lis); private void swap(char[] arr, int a, int b) char tmp = arr[a]; arr[a] = arr[b]; arr[b] = tmp;
参考资料
以上是关于LeetCode_Next Permutation的主要内容,如果未能解决你的问题,请参考以下文章
prev_permutation()和next_permutation()
STL中关于全排列next_permutation以及prev_permutation的用法
STL next_permutation和prev_permutation函数
LeetCode31 Next Permutation and LeetCode60 Permutation Sequence