我编写了一种在Java中置换整数数组的方法。但是,我无法弄清楚如何防止发现镜像排列。 例如,我想要[1,2,3]的所有排列。这些是:
[1,2,3]
[1,3,2]
[3,1,2]
[3,2,1]
[2,3,1]
[2,1,3]
最后三个排列是镜像排列,我根本不想找到。原因是,我正在尝试为旅行商问题实施强力解决方案。通过丢弃镜像的排列,我可以节省一些时间,因为游览的方向无关紧要。游览的费用是相同的。
我的想法是:如上例所示,在镜像排列中2始终位于1的前面。如果我遍历数组并找到2而不是1,则表示1保存在以后的索引中。这意味着我可以停止这种置换。但是我不知道如何执行此检查。此外,我不知道这种方法是否是解决此问题的最佳方法。 如何执行此检查?有更好的方法吗?
public void bruteforce(Graph g) {
int[] elements = new int[g.size()];
int length = g.size();
for(int i = 0; i < elements.length; i++) {
elements[i] = i;
}
permute(elements, length);
}
public void permute(int[] elements, int length) {
if(length == 1) {
for(int i = 0; i < length; i++) {
System.out.println(Arrays.toString(elements));
}
}else {
for(int i = 1; i < length; i++) {
permute(elements, length-1);
if(length % 2 == 1) {
swap(elements, 1, length-1);
}else {
swap(elements, i, length-1);
}
}
}
}
public void swap(int[] elements, int firstElement, int secondElement) {
int tmp = elements[firstElement];
elements[firstElement] = elements[secondElement];
elements[secondElement] = tmp;
}
答案 0 :(得分:1)
您可以使用equals方法创建DTO类“ Permutation”,以比较正态数组和反向数组
并将每个排列保存到Set
中,这样反向数组将重复匹配并被忽略
...
Set<Permutation> permutations = new HashSet<>();
public void permute(int[] elements, int length) {
if(length == 1) {
for(int i = 0; i < length; i++) {
permutations.add(new Permutation(elements));
}
...
public class Permutation {
private Integer[] elements;
public Permutation(Integer... elements) {
this.elements = elements;
}
@Override
public int hashCode() {
return elements.length;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Permutation other = (Permutation) obj;
// reversed elements
List<Integer> revCurElements = Arrays.asList(this.elements);
Collections.reverse(revCurElements);
if (Arrays.equals(this.elements, other.elements) || Arrays.equals(revCurElements.toArray(new Integer[1]), other.elements)) {
return true;
}
return false;
}
}