Я понимаю, что перестановки в языке программирования - очень часто задаваемый вопрос, однако я чувствую, что мой вопрос является своего рода уникальным.
Я получил ввод некоторого целого числа N
и сохранил каждую цифру в массиве, где индекс массива хранит количество раз, в котором эта цифра встречается в N
теперь я хочу проверить, поддерживается ли какая-либо функция со всеми перестановками из N исходной длины без начальных нулей. Пример:
int[] digits = new int[10];
String n = "12345675533789025";
for (char c : n.toCharArray())
digits[c-'0']++;
for (Long f : allPermutationsOf(digits))
if (someCondition(f))
System.out.println(f);
предварительным условием для следующего кода является то, что N
должно быть меньше 2 ^ 64-1 (long
максимальное значение).
Вопрос в том, как бы я принять все перестановки цифр массива и возвращает Long[]
или long[]
без использования какого - то String
конкатенации? Есть ли способ вернуть long[]
со всеми перестановками digits[]
в "Целочисленной области вещей" или, скорее, использовать только целочисленную арифметику?
Чтобы подробно остановиться на одном из приведенных выше замечаний, положить цифру d в заданное место в результате долгого времени легко: d*1
помещает его в 1-е место, d*1000
помещает его в тысячи мест и вообще d * (10^k)
помещает d
в k + 1-ю цифру. У вас есть N полных цифр для заполнения, поэтому вам нужно сделать перестановки на степенях 10 от 1 до 10 ^ (N-1).
Для требования, считая, что длина N равна n, мы можем сгенерировать все перестановки, перейдя от цифры к цифре, начиная с 0 и заканчивая при n - 1. С 0 - ведущая цифра.
Для каждой цифры мы используем только одну возможность (от 0 до 9) один раз, что позволит избежать дублирования перестановки.
От цифры x до цифры x + 1 мы можем легко сгенерировать текущее значение, передав число, называемое current
Например: на цифре 3 мы имеем ток = 1234, поэтому на цифре 4, если мы выберем 5 для цифры 4, ток будет 1234 * 10 + 5 = 12345
Пример кода в Java:
public void generate(int index, int length, int[] digits, long current, ArrayList<Long> result) {
//All the permutation will be stored in result ArrayList
for (int i = 0; i < 10; i++) {
if (digits[i] > 0 && (i != 0 || index != 0)) {
digits[i]--;
if (index + 1 == length) {//If this is the last digit, add its value into result
result.add(current * 10 + i);
} else {//else, go to next digit
generate(index + 1, length, digits, current * 10 + i, result);
}
digits[i]++;
}
}
}
Если вы ожидаете, что перестановки будут Long
любом случае, вместо представления n
в качестве массива счетчиков, было бы проще представить его как Long
.
Вот несколько способов, которыми вы можете сгенерировать перестановки.
Подумайте о создании перестановок, как нахождение следующего по величине числа с одним и тем же набором цифр, начиная с числа, состоящего из отсортированных цифр n
. В этом случае ответы на qaru.site/questions/32032/... полезны. Вы можете использовать арифметические операции и modding вместо конкатенации строк для реализации алгоритма там (я могу предоставить более подробную информацию, если хотите). Преимущество этого заключается в том, что создаваемые вами перестановки будут автоматически упорядочены.
Если вас не волнует порядок перестановок, и вы ожидаете, что количество дубликатов цифр будет небольшим, вы можете использовать алгоритм Steinhaus-Johnson-Trotter, который (по словам Роберта Седжуика) является самым быстрым алгоритмом генерации перестановок уникальные элементы. Чтобы убедиться, что повторяющиеся перестановки не сгенерированы, вам нужно будет различать каждую повторяющуюся цифру и только выделять перестановки, где они отображаются в порядке (т. 2_1
Если 2
появляется три раза, тогда создайте элементы 2_1
, 2_2
, 2_3
и убедитесь, что эти три элементы всегда появляются в этом порядке в испущенной перестановке).