约翰逊特罗特算法
概述:
我正在尝试用 Java 实现 Johnson Trotter 算法,以便解决 项目上的问题欧拉。我看了又看,但据我所知,我已经正确实现了所有内容,你知道这是错误的,否则我不会问这个问题:)
基本算法是这样的:
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)
。当我交换值时,只发生一次交换,然后一遍又一遍地打印原始订单。
代码:
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
第一次交换后它不会改变
任何帮助都会很棒,如果你有评论/指针我的风格,这些也将不胜感激,谢谢。
抱歉发帖太长。
Overview:
I am trying to implement the Johnson Trotter Algorithm in Java so that I can solve a problem on Project Euler. I have looked and looked but as far as I can see I have everything implemented right, which you know is wrong, otherwise I wouldn't be asking this question :)
The basic algorithm goes like this:
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
I have created an Element
object that has attributes (value, isMobile, Direction)
to use for this algorithm. When I am swapping values, only one swap occurs, then after that the original order is printed over and over.
Code:
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;
}
Expectations:
I would expect the algorithm to do something like this
Start:
<0 <1 <2
<0 <2 <1
<2 <0 <1
etc
Actual
This is what it actually does
Start:
<0 <1 <2
<0 <2 <1
<0 <2 <1
<0 <2 <1
it doesnt change after the first swap
Any help would be awesome, also if you have comments/pointers about my style those would also be much appreciated, Thanks.
Sorry for long post.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尽管您没有在这里发布完整的代码(如何确定元素是移动的还是不动的会有所帮助),但我怀疑您的错误来自这里:
因为算法说
找到最大的移动元素K
。另外,我怀疑您的
isMobile
方法存在问题,但无法确定。希望这有帮助!
Although you are not posting the complete code here (how you decide if an element is mobile or immobile would be helpful), I suspect your error comes from here:
Since the algorithm said
find the largest mobile element K
.Also, I suspect there are problems for your
isMobile
method, but cannot be sure.Hope this helps!
我查看了 Even 加速的建议链接,认为使用比较的效率不必要地低。我的理解是 Even 的加速意味着你不需要比较。
这是我的代码;这种迭代形式(与递归解决方案不同)允许您调用 getNext 迭代器来生成并返回下一个排列。
I looked at the suggested link with Even's speedup and think it is unnecessarily inefficient, using compares. My understanding is that Even's speedup means you don't need compares.
Here's my code; this iterative form (unlike the recursive solution) allows you to call a getNext iterator to generate and return the next permutation.
您甚至可以从 此处
You can even download the complete java source code for this, with Even's speedup from here
的 java 代码
这是 Johson Trotter 算法公共类 PermutationGenerator
{
}
Here is the java code for Johson Trotter Algorithm
public class PermutationGenerator
{
}