产生的变化没有重复/排列在java
-
19-09-2019 - |
题
我已经产生的所有变化没有重复出现的数字是0-9.
长他们可以从1到10。我真的不知道如何解决这个问题,特别是如何避免重复。
例如:长度的变化:4 随机的变化:9856,8753,1243,1234等。(但不9985-包含重复)
我将很感谢如果有人可以帮我这个问题,特别是给予一些代码和线索。
解决方案
要查找的关键字是置换。有丰富的源代码免费提供的,其执行它们。
至于保持其重复自由,我建议一个简单的递归方法:为每一个数字,你有考虑到你的变化或不选择的,所以你的递归计算通过数字和叉成两个递归调用,一个在其中数字被包括在内,在其中它被排除。然后,你到达最后一位数字后每次递归本质上给你一个(唯一,排序)的免费重复位数列表。然后,您可以创建这个列表的所有可能的排列和组合所有这些的排列来实现你的最终结果。
(同duffymo说:我不会为提供代码)
高级注:递归基于0/1(排斥,夹杂物),其可直接被转换成比特,因此,整数。因此,为了得到所有可能的数字组合,而无需实际执行递归本身,你可以简单地使用所有的10位整数,并遍历它们。然后解释的数字,使得一组位对应于包括需要被置换列表中的数字。
其他提示
这里是我的Java代码。随便问如果你不理解。主要的一点是:
- 排序再次符阵列。例如:a1a2a3b1和b2b3。...(a1=a2=a3)
- 产生的排列,并始终保持条件:索引的a1 < 指标a2 < 索引的a3...
import java.util.Arrays;
public class PermutationDup {
public void permutation(String s) {
char[] original = s.toCharArray();
Arrays.sort(original);
char[] clone = new char[s.length()];
boolean[] mark = new boolean[s.length()];
Arrays.fill(mark, false);
permute(original, clone, mark, 0, s.length());
}
private void permute(char[] original, char[] clone, boolean[] mark, int length, int n) {
if (length == n) {
System.out.println(clone);
return;
}
for (int i = 0; i < n; i++) {
if (mark[i] == true) continue;
// dont use this state. to keep order of duplicate character
if (i > 0 && original[i] == original[i-1] && mark[i-1] == false) continue;
mark[i] = true;
clone[length] = original[i];
permute(original, clone, mark, length+1, n);
mark[i] = false;
}
}
public static void main(String[] args) {
PermutationDup p = new PermutationDup();
p.permutation("abcab");
}
}
我已经创建了下面的代码,其中的顺序很重要,并与任何重复产生置换。这使得使用泛型用于置换任何类型的对象:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Permutations {
public static <T> Collection<List<T>> generatePermutationsNoRepetition(Set<T> availableNumbers) {
Collection<List<T>> permutations = new HashSet<>();
for (T number : availableNumbers) {
Set<T> numbers = new HashSet<>(availableNumbers);
numbers.remove(number);
if (!numbers.isEmpty()) {
Collection<List<T>> childPermutations = generatePermutationsNoRepetition(numbers);
for (List<T> childPermutation : childPermutations) {
List<T> permutation = new ArrayList<>();
permutation.add(number);
permutation.addAll(childPermutation);
permutations.add(permutation);
}
} else {
List<T> permutation = new ArrayList<>();
permutation.add(number);
permutations.add(permutation);
}
}
return permutations;
}
}
假设你有一个神奇的功能 - 给出的数字的阵列,它会返回你正确的排列。
您如何使用该功能来产生置换的新名单只有一个额外的数字?
如,
如果我给你一个名为permute_three(char[3] digits)
功能,我告诉你,它仅适用于数字0
,1
,2
,你怎么能写能置换0
de,1
,2
,3
,使用给定permute_three
功能的功能?
...
一旦你解决了,你发现了什么?你可以概括呢?
使用元的它很简单:
@Test
public void generatePermutations() {
// digits is the string "0123456789"
String digits = $('0', '9').join();
// then generate 10 permutations
for (int i : $(10)) {
// shuffle, the cut (0, 4) in order to get a 4-char permutation
System.out.println($(digits).shuffle().slice(4));
}
}
代码为这是类似于一个没有重复,与另外一个如果其他的发言。检查这个 代码
在上述码、编辑为如下环路
for (j = i; j <= n; j++)
{
if(a[i]!=a[j] && !is_duplicate(a,i,j))
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j));
}
else if(i!=j) {} // if no duplicate is present , do nothing
else permute(a,i+1,n); // skip the ith character
}
bool is_duplicate(int *a,int i,int j)
{
if a[i] is present between a[j]...a[i]
return 1;
otherwise
return 0;
}
为我工作
没有重复置换是基于定理,结果的量是阶乘元素计数(在这种情况下的数字)。你的情况10!是10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3628800.证明为什么它被完全正确是用于产生正确的解决方案也。 那么这样如何。在IE浏览器从左边第一个位置,你可以有10个号码,在第二位置,你只能有9的数字,因为一个号是在左边的位置,我们不能重复相同的号码等(证明由数学归纳法完成)。 那么如何产生前十名的结果?根据我的知识,他最简单的方法是使用循环移位。这意味着数左移一个位置(或右如果你想),并把对空位置上溢数的顺序。 这意味着对于第一十个结果:
10 9 8 7 6 5 4 3 2 1,点击 9 8 7 6 5 4 3 2 1 10,点击 8 7 6 5 4 3 2 1 10 9,点击 7 6 5 4 3 2 1 10 9 8,点击 6 5 4 3 2 1 10 9 8 7,点击 5 4 3 2 1 10 9 8 7 6,点击 ...
的第一行是基本样品,所以它是把它放入代之前设置好主意。优点是,在下一步骤中,你将不得不解决同样的问题,以避免不希望的duplicities。
在下一步骤递归地仅旋转10-1号10-1倍等 这意味着对于第一9个结果在步骤二:
10 9 8 7 6 5 4 3 2 1,点击 10 8 7 6 5 4 3 2 1 9,点击 10 7 6 5 4 3 2 1 9 8,点击 10 6 5 4 3 2 1 9 8 7,点击 10 5 4 3 2 1 9 8 7 6,点击 ...
等,通知,该第一行是从以前的步骤中存在,所以它必须不被添加到生成的再次设定。
算法递归地做正是,什么是上面所解释的。它可以生成所有10 3628800个组合!因为嵌套的数量是相同的数组元素的数量(这意味着你的情况为10个号码就徘徊约5分钟。我的电脑上),你需要有足够的内存如果你想保持所有组合的阵列。
有是溶液。
package permutation;
/** Class for generation amount of combinations (factorial)
* !!! this is generate proper permutations without repeating and proper amount (počet) of rows !!!
*
* @author hariprasad
*/
public class TestForPermutationII {
private static final String BUMPER = "*";
private static int counter = 0;
private static int sumsum = 0;
// definitoin of array for generation
//int[] testsimple = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] testsimple = {1, 2, 3, 4, 5};
private int ELEMNUM = testsimple.length;
int[][] shuff;
private String gaps(int len) {
String addGap = "";
for(int i=0; i <len; i++)
addGap += " ";
return addGap;
}
/** Factorial computing */
private int fact(int num) {
if (num > 1) {
return num * fact(num - 1);
} else {
return 1;
}
}
/** Cyclic shift position to the left */
private int[] lShiftPos(int[] arr, int pos) {
int[] work = new int[ELEMNUM];
int offset = -1;
for (int jj = 0; jj < arr.length; jj++) {
if (jj < pos) {
work[jj] = arr[jj];
} else if (jj <= arr.length - 1) {
if (jj == pos) {
offset = arr[pos]; // last element
}
if (jj != (arr.length - 1)) {
work[jj] = arr[jj + 1];
} else {
work[jj] = offset;
}
}
}
return work;
}
private String printBuff(int[] buffer) {
String res = "";
for (int i= 0; i < buffer.length; i++) {
if (i == 0)
res += buffer[i];
else
res += ", " + buffer[i];
}
return res;
};
/** Recursive generator for arbitrary length of array */
private String permutationGenerator(int pos, int level) {
String ret = BUMPER;
int templen = counter;
int[] work = new int[ELEMNUM];
int locsumread = 0;
int locsumnew = 0;
//System.out.println("\nCalled level: " + level);
for (int i = 0; i <= templen; i++) {
work = shuff[i];
sumsum++;
locsumread++;
for (int ii = 0; ii < pos; ii++) {
counter++;
sumsum++;
locsumnew++;
work = lShiftPos(work, level); // deep copy
shuff[counter] = work;
}
}
System.out.println("locsumread, locsumnew: " + locsumread + ", " + locsumnew);
// if level == ELEMNUM-2, it means no another shift
if (level < ELEMNUM-2) {
ret = permutationGenerator(pos-1, level+1);
ret = "Level " + level + " end.";
//System.out.println(ret);
}
return ret;
}
public static void main(String[] argv) {
TestForPermutationII test = new TestForPermutationII();
counter = 0;
int len = test.testsimple.length;
int[] work = new int[len];
test.shuff = new int[test.fact(len)][];
//initial
test.shuff[counter] = test.testsimple;
work = test.testsimple; // shalow copy
test.shuff = new int[test.fact(len)][];
counter = 0;
test.shuff[counter] = test.testsimple;
test.permutationGenerator(len-1, 0);
for (int i = 0; i <= counter; i++) {
System.out.println(test.printBuff(test.shuff[i]));
}
System.out.println("Counter, cycles: " + counter + ", " + sumsum);
}
}
算法的强度(循环数)为成员的数目的不完全阶乘总和。所以当局部设置被再次读取以生成下一个子集突出端,所以强度是:
N! + N!/ 2! + N!/ 3! + ... + N!/(N-2)! + N!(N-1)!
有一个解决方案,它是不是从矿,但它是非常好的,复杂的。
package permutations;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* @author Vladimir Hajek
*
*/
public class PermutationSimple {
private static final int MAX_NUMBER = 3;
Set<String> results = new HashSet<>(0);
/**
*
*/
public PermutationSimple() {
// TODO Auto-generated constructor stub
}
/**
* @param availableNumbers
* @return
*/
public static List<String> generatePermutations(Set<Integer> availableNumbers) {
List<String> permutations = new LinkedList<>();
for (Integer number : availableNumbers) {
Set<Integer> numbers = new HashSet<>(availableNumbers);
numbers.remove(number);
if (!numbers.isEmpty()) {
List<String> childPermutations = generatePermutations(numbers);
for (String childPermutation : childPermutations) {
String permutation = number + childPermutation;
permutations.add(permutation);
}
} else {
permutations.add(number.toString());
}
}
return permutations;
}
/**
* @param args
*/
public static void main(String[] args) {
Set<Integer> availableNumbers = new HashSet<>(0);
for (int i = 1; i <= MAX_NUMBER; i++) {
availableNumbers.add(i);
}
List<String> permutations = generatePermutations(availableNumbers);
for (String permutation : permutations) {
System.out.println(permutation);
}
}
}
我认为,这是优良的解决方案。
附图有帮助置换索引知识
创建生成正确排列,给出0和N之间{的索引值的方法! -1}为“零索引”或{1和N!}为“一个索引”。
创建包含的第二方法的“for循环”,其中下限是1,而上限是N!例如.. “对于(I; I <= N!;我++)” 为环的每个实例调用第一个方法,传递我作为参数