如何有效地散列二维数组(存储在HashSet中)?

时间:2010-10-23 11:28:14

标签: java arrays hashcode hashset multidimensional-array

我写了一个名为PuzzleBoard的类,代表一个nxn板。我将在HashSet中保留几个PuzzleBoard对象,因此我必须覆盖'int hashCode()'方法。

以下是我班级的字段:

 private int N;
 private int[][] puzzle;
 private int blankCellX;
 private int blankCellY;
 private int cost;

Eclipse为我自动生成的是:

 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + N;
  result = prime * result + blankCellX;
  result = prime * result + blankCellY;
  result = prime * result + cost;
  result = prime * result + Arrays.hashCode(puzzle);
  return result;
 } 

认为这种方法没有考虑二维数组的内容,我将其改为:

 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + N;
  result = prime * result + blankCellX;
  result = prime * result + blankCellY;
  result = prime * result + cost;
  for (int i = 0; i < N; ++i)
   result = prime * result + Arrays.hashCode(puzzle[i]);
  return result;
 } 

然而,这种方法的问题是完成时间太长:O(N ^ 2) 此外; 'result'变量很可能会溢出。

现在,我的问题是,如何编写一个不需要太长时间才能完成的高效哈希方法。此外;在HashSet中插入或搜索对象应该是有效的(接近恒定时间)。

在最坏的情况下,N将为10,HashSet将包含~1000 PuzzleBoards。

为什么我要做这一切? 我正在使用A *算法实现N-Puzzle问题的解决方案。因此,在算法的某个阶段,给定当前节点(板的配置),我正在向上,向下,向右或向左移动空白单元以生成新的子节点。因此,拼图配置通常相差1或2个单元格。我将所有已探索的节点存储在HashSet中。

提前致谢=)

2 个答案:

答案 0 :(得分:1)

哈希码不需要 是唯一的,如果它们更好的话。由于HashSet(~1000)中的项目数量相对较少,因此您可以选择少量合适的数据进行哈希处理。例如,您可能只需要“拼图”表的第一行,或者“成本”变量可能因不同的实例而大不相同,您可以将其用作差异的良好来源。

结果是否溢出并不重要:如果可能,您想要的是让不同的对象返回不同的哈希码。哈希的实际值并不重要。

答案 1 :(得分:1)

  

此方法未考虑二维数组的内容

您也可以使用util.Arrays#deepHashCode()

  

然而,这种方法的问题是完成时间太长:O(N ^ 2)

如果你想要散列其中的所有N ^ 2个整数,你不能走得更快?如果N最多为10,那么Big-O符号是什么? O(n^2)并不意味着缓慢。我不认为你的hashCode方法效率低下。低效率或某些O(n^2)很可能在其他地方......如果经常调用此方法(并且PuzzleBoard是不可变的),您可能希望缓存hashCode值。

  

'result'变量很可能会溢出。

没问题!溢出在Java中定义。

  

此外;在HashSet中插入或搜索对象应该是有效的(接近恒定时间)。

插入很可能只是摊销常量时间。当HashSet变满时,将创建一个新的更大的HashSet。所有元素都复制在其中,所有的hashCodes都必须再次计算。尝试为HashSet设置initialCapacity?

result = prime * result + cost;

您确定要将成本(我认为是深度)包含在equals和hashCode中吗?两个配置是相同的,无论我走多少步,对吧?

  

~1000 PuzzleBoards

如果我没记错的话,上次我解决了这个难题,我已经很多超过1000个配置。