Java 继任人(候选人); 计数器--; } 返回rollOverToStart(计数器,候选者.iterator().next()); } 私有集合allLetters(){ Set letters=newlinkedhashset(); 字母=头; for(int i=0;i
在Java 继任人(候选人); 计数器--; } 返回rollOverToStart(计数器,候选者.iterator().next()); } 私有集合allLetters(){ Set letters=newlinkedhashset(); 字母=头; for(int i=0;i,java,overriding,hashcode,circular-list,Java,Overriding,Hashcode,Circular List,在getstartofsmalestrotation中实现的算法找到单词的字典最小旋转,基本上就是我上面描述的:比较并选择每个旋转的字典最小的第一、第二、第三等字母,删除较大的字母,直到只剩下一个候选字母,或者你把这个词翻过来。因为列表是循环的,所以我使用计数器来避免无限循环 最后,如果我有一个单独的候选者,它可能在单词的中间,我需要开始最小的单词旋转。然而,由于这是一个单独链接的列表,因此在其中后退是很尴尬的。幸运的是,计数器很好地帮助了我:它记录了到目前为止我比较过的字母数量,但在循环列表中
getstartofsmalestrotation
中实现的算法找到单词的字典最小旋转,基本上就是我上面描述的:比较并选择每个旋转的字典最小的第一、第二、第三等字母,删除较大的字母,直到只剩下一个候选字母,或者你把这个词翻过来。因为列表是循环的,所以我使用计数器来避免无限循环
最后,如果我有一个单独的候选者,它可能在单词的中间,我需要开始最小的单词旋转。然而,由于这是一个单独链接的列表,因此在其中后退是很尴尬的。幸运的是,计数器很好地帮助了我:它记录了到目前为止我比较过的字母数量,但在循环列表中,这相当于我在翻滚之前可以向前移动的字母数量。因此,我知道要向前移动多少个字母,以便再次到达我正在寻找的最小单词旋转的开头
希望这有助于某人-至少写起来很有趣:-)我误解了你的问题-我以为你想要不同的haschodes来表示“picture”和“turepic”;我认为在这种情况下,您可以从以下事实中得到一个提示:两个相等的对象必须具有相同的哈希代码,但具有相同哈希代码的两个对象不一定相等 因此,您可以使用Vivien的解决方案,该解决方案将保证“picture”和“turepic”具有相同的哈希代码。然而,这也意味着“picture”和“pitcure”也将具有相同的哈希代码。在这种情况下,您的
equals
方法必须更加智能,并且必须确定这两个字母列表是否代表同一个单词。本质上,equals方法有助于解决“picture”/“turepic”和“pitcure”之间的冲突
因为+是可交换的,所以相等的字将具有相等的哈希码。hashcode不是很有区别(所有字母排列都得到相同的hash码),但它应该可以做到这一点,除非您通常在HashSet中放入许多排列
注意:我添加了c*c
,而不是简单地添加c
,以减少不同字母的冲突
注2:哈希代码相等的不相等列表不违反哈希代码合同。应该避免这种“冲突”,因为它们会降低性能,但不会威胁程序的正确性。一般来说,冲突是无法避免的,尽管与我的回答相比,避免冲突的可能性肯定更大,但这样做会使哈希代码的计算成本更高,这可能会消耗更多的性能增益
字母定义equals()
和hashCode()
。仅使用char
字段执行此操作
CircularWord
,通过从head
迭代到tail
XOR'ingLetter.hashCode
的相应值来实现hashCode()
。最后用某个常数对结果进行异或运算另一种方法是规范化循环词,将其表示为:
public class CircularWord {
private static Set<String> canonicalWords = new HashSet<String>();
private String canonicalWord;
private int offset;
public CircularWord(String word) {
// Looks for an equal cirular word in the set (according to our definition)
// If found, set canonicalWord to it and calculate the offset.
// If not found, put the word in the set, set canonical word to our argument and set offset to 0.
}
// Implementation of CircularWord methods using
// canonicalWord and offset
}
公共类循环词{
私有静态集canonicalWords=new HashSet();
私有字符串规范字;
私有整数偏移;
公共通告词(字符串字){
//在集合中查找相等的循环词(根据我们的定义)
//如果找到,将canonicalWord设置为它并计算偏移量。
//如果找不到,则将单词放入集合中,将规范单词设置为参数,并将偏移量设置为0。
}
//循环词方法的实现
//规范字和偏移量
}
然后,您可以通过委托给
字符串实现来实现equals()
和hashCode()
。请记住,hashCode不是唯一的。两个不同的对象可以散列为完全相同的值。因此hashcode不足以确定相等性;您必须在equals()中进行实际比较。[已删除推测性评论。OMG]
hashcode()在所有情况下都只能返回一个常量。这可能会影响性能,但它是完全有效的。完成所有其他工作后,就可以使用更高效的hashcode()算法了
。注意“惰性哈希代码”部分。您真的需要使用哈希代码吗?如果不打算将对象成员放置在任何类型的哈希结构中,可以忽略以下问题:
public int hashCode() {
return 5;
}
这就满足了
public class CircularWord {
private final Letter head;
private final int numberOfElements;
// constructor, toString(), equals() omitted
@Override
public int hashCode() {
return hashCodeStartingFrom(getStartOfSmallestRotation());
}
private Letter getStartOfSmallestRotation() {
if (head == null) {
return null;
}
Set<Letter> candidates = allLetters();
int counter = numberOfElements;
while (candidates.size() > 1 && counter > 0) {
candidates = selectSmallestSuccessors(candidates);
counter--;
}
return rollOverToStart(counter, candidates.iterator().next());
}
private Set<Letter> allLetters() {
Set<Letter> letters = new LinkedHashSet<Letter>();
Letter letter = head;
for (int i = 0; i < numberOfElements; i++) {
letters.add(letter);
letter = letter.getNext();
}
return letters;
}
private Set<Letter> selectSmallestSuccessors(Set<Letter> candidates) {
Set<Letter> smallestSuccessors = new LinkedHashSet<Letter>();
char min = Character.MAX_VALUE;
for (Letter letter : candidates) {
Letter nextLetter = letter.getNext();
if (nextLetter.getValue() < min) {
min = nextLetter.getValue();
smallestSuccessors.clear();
}
if (nextLetter.getValue() == min) {
smallestSuccessors.add(nextLetter);
}
}
return smallestSuccessors;
}
private Letter rollOverToStart(int counter, Letter lastCandidate) {
for (; counter >= 0; counter--) {
lastCandidate = lastCandidate.getNext();
}
return lastCandidate;
}
private int hashCodeStartingFrom(Letter startFrom) {
int hash = 0;
Letter letter = startFrom;
for (int i = 0; i < numberOfElements; i++) {
hash = 31 * hash + letter.getValue();
letter = letter.getNext();
}
return hash;
}
}
int hashcode() {
int hash = 0;
for (c in list) {
hash += c * c;
}
return hash;
}
public class CircularWord {
private static Set<String> canonicalWords = new HashSet<String>();
private String canonicalWord;
private int offset;
public CircularWord(String word) {
// Looks for an equal cirular word in the set (according to our definition)
// If found, set canonicalWord to it and calculate the offset.
// If not found, put the word in the set, set canonical word to our argument and set offset to 0.
}
// Implementation of CircularWord methods using
// canonicalWord and offset
}
public int hashCode() {
return 5;
}
hash = 0
for each rotation
hash += hash(permutation)
end
hash %= MAX_HASH