Problem 24
Lexicographic permutations
A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:
What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
字典序排列
排列指的是将一组物体进行有顺序的放置。例如,3124是数字1、2、3、4的一个排列。如果把所有排列按照数字大小或字母先后进行排序,我们称之为字典序排列。0、1、2的字典序排列是:
数字0、1、2、3、4、5、6、7、8、9的字典序排列中第一百万位的排列是什么?
package projecteuler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Test;
public class Prj24 {
/**
* A permutation is an ordered arrangement of objects. For example, 3124 is
* one possible permutation of the digits 1, 2, 3 and 4. If all of the
* permutations are listed numerically or alphabetically, we call it
* lexicographic order. The lexicographic permutations of 0, 1 and 2 are:
*
* 012 021 102 120 201 210
*
* What is the millionth lexicographic permutation of the digits 0, 1, 2, 3,
* 4, 5, 6, 7, 8 and 9?
*/
@Test
public void test() {
System.out.println(Calculator.calculate(1000000));
System.out.println(9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1);
}
public static class Calculator {
public static String calculate(int upLimit) {
Set<Integer> set = new HashSet<Integer>();
int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int val : arr) {
set.add(val);
}
int[] outArr = new int[10];
nextPermutation(upLimit, set, outArr);
return arr2Str(outArr);
}
public static void nextPermutation(int num, Set<Integer> dataSet,
int[] outArr) {
int limit = num;
int count = outArr.length;
for (int i = 0; i < count; i++) {
int size = getN(dataSet.size() - 1);
int j = 0;
for (; j < dataSet.size() - 1; j++) {
if (j * size <= limit && (j + 1) * size > limit) {
break;
}
}
outArr[i] = getMax(dataSet, j);
dataSet = removeSetByVal(dataSet, outArr[i]);
limit -= j * size;
if (limit == 0) {
List<Integer> tmp = new ArrayList<Integer>();
tmp.addAll(dataSet);
Collections.sort(tmp);
for (int k = i + 1; k < outArr.length; k++) {
outArr[k] = tmp.get(tmp.size() - 1 - (k - i - 1));
}
return;
}
}
}
private static String arr2Str(int[] val) {
StringBuffer sb = new StringBuffer();
for (int iv : val) {
sb.append(iv);
}
return sb.toString();
}
@Deprecated
private static String arr2Str(List<Integer> val) {
StringBuffer sb = new StringBuffer();
for (int iv : val) {
sb.append(iv);
}
return sb.toString();
}
@Deprecated
private static void iterSet(Set<Integer> dataSet, List<Integer> arr,
int limit, int index) {
if (limit == 0) {
return;
}
int size = getN(dataSet.size() - 1);
int i = 0;
for (; i < dataSet.size() - 1; i++) {
if (i * size <= limit && (i + 1) * size > limit) {
break;
}
}
arr.add(getMax(dataSet, i));
Set<Integer> setRemoveThisNum = removeSetByVal(dataSet,
arr.get(index));
List<Integer> nextIterArrCopy = copyList(arr);
iterSet(setRemoveThisNum, nextIterArrCopy, limit - i * size,
index + 1);
arr = copyList(nextIterArrCopy);
}
private static List<Integer> copyList(List<Integer> arr) {
List<Integer> ret = new ArrayList<Integer>();
for (int i = 0; i < arr.size(); i++) {
ret.add(arr.get(i));
}
return ret;
}
private static Set<Integer> removeSetByVal(Set<Integer> dataSet, int val) {
Set<Integer> ret = new HashSet<Integer>(dataSet);
ret.remove(val);
return ret;
}
private static int getMax(Set<Integer> dataSet, int id) {
List<Integer> data = new ArrayList<Integer>();
data.addAll(dataSet);
Collections.sort(data);
return data.get(id);
}
public static int getN(int num) {
int sum = 1;
for (int i = 0; i < num; i++) {
sum *= (i + 1);
}
return sum;
}
}
}