概述:
我试图在Java中实现Johnson Trotter算法,以便解决Euler项目上的问题。我看了看,但据我所知,我已正确实现了所有内容,您知道这是错误的,否则我不会问这个问题:)
基本算法如下:
Johnson Trotter(n) //Input: A positive integer n //Output: A list of all permutations(0..n) initialize the first permutation with: <0, <1, <2 //(all elements pointing left) while ( //there exists a mobile element ) //find the largest mobile element K //swap K with the element it points toward //reverse the direction of all elements > K //add the permutation to a list
我创建了一个Element对象,该对象具有(value, isMobile, Direction)可用于此算法的属性。当我交换值时,仅发生一次交换,然后一遍又一遍地打印原始订单。
Element
(value, isMobile, Direction)
码:
public void generatePermutations(int n) { ArrayList<String> permutations = new ArrayList<String>(); ArrayList<Element> elements = new ArrayList<Element>(); //Initialize the first permutation, //all Elements are mobile and point LEFT for(int i = 0; i < n; i++) { elements.add(new Element(i, true, Direction.LEFT)); } //add initial permutation to the list permutations.add(combineElementsToString(elements)); while(hasMobileElement(elements)) { //find the largest mobile element int maxIndex = getLargestMobileIndex(elements); Element k = elements.get(maxIndex); //Swap the largest Element with the Element it points to if(k.getDirection() == Direction.LEFT) { //get the index of the element to the left of k int leftIndex = (maxIndex - 1) >= 0 ? (maxIndex - 1) : maxIndex; Collections.swap(elements, maxIndex, leftIndex); } else { //get the index of the element to the right of k int rightIndex = (maxIndex + 1) < elements.size() ? (maxIndex + 1) : maxIndex; Collections.swap(elements, maxIndex, rightIndex); } //reverse the direction of all elements larger than K for(Element e : elements) { //System.out.println(e); if(e.getValue() > k.getValue()) { Direction opposite = Direction.opposite(e.getDirection()); e.setDirection(opposite); } } //add the new permutation to the list permutations.add(combineElementsToString(elements)); if(STOP++ == 10) System.exit(0); } } //converts all the values of the Element //objects then adds them to a String public String combineElementsToString(ArrayList<Element> elements) { String perm = ""; for(Element e : elements) { perm += Integer.toString(e.getValue()); } return perm; } //finds largest Mobile element and returns it's index public int getLargestMobileIndex(ArrayList<Element> elements) { int maxIndex = 0; for(int i = 0; i < elements.size(); i++) { if(elements.get(i).isMobile() && i > maxIndex) { maxIndex = i; } } return maxIndex; } //determines if there is a remaining mobile element public boolean hasMobileElement(ArrayList<Element> elements) { for(Element e : elements) { if(e.isMobile()) return true; } return false; }
期望: 我希望算法能做这样的事情
开始:
<0 <1 <2 <0 <2 <1 <2 <0 <1
等等
实际
这就是它的实际作用
<0 <1 <2 <0 <2 <1 <0 <2 <1 <0 <2 <1
第一次交换后它没有改变
任何帮助都会很棒,如果您对我的风格有意见/建议,也将不胜感激,谢谢。
抱歉,很长的帖子。
尽管您没有在此处发布完整的代码(如何确定元素是可移动还是不可移动是很有帮助的),但我怀疑您的错误来自此处:
public int getLargestMobileIndex(ArrayList<Element> elements) { int maxIndex = 0; for(int i = 0; i < elements.size(); i++) { if(elements.get(i).isMobile() && i > maxIndex) //<---------- It seems that // you should compare the i-th element to the maxIndex-th element, not i and // maxIndex { maxIndex = i; } } return maxIndex; }
自算法说find the largest mobile element K。
find the largest mobile element K
另外,我怀疑您的isMobile方法有问题,但不能确定。
isMobile
希望这可以帮助!