https://oj.leetcode.com/problems/next-permutation/
http://fisherlei.blogspot.com/2012/12/leetcode-next-permutation.html
public class Solution {
public void nextPermutation(int[] num) {
// Solution B
nextPermutation_Math(num);
// Solution A
// nextPermutation_AllPerms(num);
}
///////////////////////////////////////
// Solution A: Generate all permutations for num
// Sort it
// Find the next one.
public void nextPermutation_AllPerms(int[] num) {
// All perms
List<List<Integer>> allperms = new ArrayList<>();
allperms(num, 0, allperms);
// Sort
Collections.sort(allperms, new Comparator<List<Integer>>()
{
public int compare(List<Integer> a, List<Integer> b)
{
int len = a.size();
for (int i = 0 ; i < len ; i ++)
{
if (a.get(i) != b.get(i))
{
return Integer.compare(a.get(i), b.get(i));
}
}
return 0;
}
});
// Find
int pos = allperms.indexOf(listof(num));
pos = (pos + 1) % allperms.size();
for (int i = 0 ; i < num.length ; i ++)
{
num[i] = allperms.get(pos).get(i);
}
}
// See Permutations II
private void allperms(int[] n, int start, List<List<Integer>> result)
{
int len = n.length;
if (start >= len)
{
// A result found.
result.add(listof(n));
}
for (int i = start ; i < len ; i ++)
{
// If we have any dups from start to i.
// No need to continue recursion
//
// 注意不要误以为以下两种做法能够去重:
// (1)最开始先对数组进行排序,以后每次交换时,只要保证当前要交换的元素和前一个元素不同,这种做法是错误的.
// 虽然开始进行了排序,但是元素的交换会使数组再次变的无序
// (2)每次进入递归函数permuteRecur时,对从当前索引开始的子数组排序,这种做法也是错误的.
// 因为每次交换元素后,我们要恢复交换的元素,如果在递归函数内排序,就不能正确的恢复交换的元素。
if (unique(n, start, i))
// if (n[start] != n[i])
{
swap(n, i, start);
allperms(n, start + 1, result);
swap(n, i, start);
}
}
}
private boolean unique(int[] n, int start, int end)
{
for (int i = start ; i < end ; i ++)
{
if (n[i] == n[end])
return false;
}
return true;
}
///////////////////////////////////////
// Solution B: A math
// I don‘t know why
//
public void nextPermutation_Math(int[] num) {
if (num == null || num.length <= 1)
return; // No need continue
// Step 1, search from right to left.
// Find the first index break increase.
//
// Step 2, search from right to left
// Find the first index with value > firstindex.
//
// Step 3, swap firstindex and secondindex
//
// Step 4, reverse all elements after first index.
// Step 1
int firstindex = -1;
int len = num.length;
for (int i = len - 1 ; i > 0 ; i --)
{
if (num[i - 1] < num[i])
{
firstindex = i - 1;
break;
}
}
if (firstindex == -1)
{
// All decrease.
// Reverse all
reverse(num, 0);
return;
}
// Step 2
int secondindex = num.length - 1;
while (secondindex > firstindex)
{
if (num[secondindex] > num[firstindex])
break;
secondindex --;
}
if (secondindex == firstindex)
return; // invalid
// Step 3
swap(num, firstindex, secondindex);
// Step 4
reverse(num, firstindex + 1);
}
/////////////////////////////////////
//
// Tools
// Reverse num from s(inclusive) to the end
private void reverse(int[] num, int s)
{
int i = s;
int j = num.length - 1;
while (i < j)
{
swap(num, i, j);
i ++;
j --;
}
}
private void swap(int[] num, int i , int j)
{
int t = num[i];
num[i] = num[j];
num[j] = t;
}
private List<Integer> listof(int[] n)
{
List<Integer> toReturn = new ArrayList<>(n.length);
for (int i : n)
toReturn.add(i);
return toReturn;
}
}原文:http://7371901.blog.51cto.com/7361901/1598434