【问题标题】:Overriding the Hashcode func for Sliding Puzzle problem覆盖滑动拼图问题的哈希码函数
【发布时间】:2021-10-08 12:37:00
【问题描述】:

我正在为滑动拼图的每个状态分配一个哈希码。我目前拥有的代码为不同的状态返回相同的哈希码。有谁知道唯一散列滑动拼图状态的有效方法?

public int hashCode() {
    int total = 2;


    if(board[0][0] == -1) {
        total += 9;
    }
    else{
        total += 9 * board[0][0];
    }

    if(board[0][1] == 1){
        total += 1;
    }
    else{
        total += 1 * board[0][1];
    }

    if(board[0][2] == 2){
        total += 2;
    }
    else{
        total += 2 * board[0][2];
    }

    if(board[1][0] == 3){
        total += 3;
    }
    else{
        total += 3 * board[1][0];
    }

    if(board[1][1] == 4){
        total += 4;
    }
    else{
        total += 4 * board[1][1];
    }

..等

【问题讨论】:

  • 我剪掉了其余的代码来提交这篇文章,但它运行相同的逻辑
  • 有多少个插槽,可能有多少种不同的状态?组合的数量很可能超过 2^32,这意味着您无法在 int hashCode() 中进行完美的散列。正如 dratenik 在下面指出的那样,这通常不是问题。
  • 问题中的代码建议使用 3x3 板,也可以通过使用字段内容作为按顺序读取的十进制数字的不那么雄心勃勃的方法对其进行唯一编码。这仍然适合 32 位 int(最大结果 876543210)。

标签: java hashcode


【解决方案1】:

计算数组的哈希码是 Java API 提供的一种常见任务:

Arrays.deepHashCode(board)

(如果您对数组的内容有更多的了解,您可能能够制作出更好的哈希码函数,但通用的函数相当不错,您的时间可能会花在其他地方进行优化)

如果您好奇 Java API 是如何做到这一点的,这里是实现的重要部分:

public static int hashCode(int a[]) {
    if (a == null)
        return 0;

    int result = 1;
    for (int element : a)
        result = 31 * result + element;

    return result;
}

如您所见,该实现在添加下一个元素之前将前一个结果乘以一个常数。如果我们想象结果存储在以 31 为基数的positional number system 中,这会将前一个结果的数字向左移动一位,然后在最低位添加有关新元素的信息。因为之前的数字已经被移开了,所以新旧数字之间没有重叠,只要结果不溢出就可以完美地重构信息。并且即使结果溢出,它也会被 2 的幂约减,并且由于 31 与 2 互质,一些关于旧数字的信息将保留。

如果您知道您的数组包含少量数字(例如,小于 15),则最好乘以 15 而不是 31,因为它可以在开始溢出之前对更多元素进行编码,从而产生更好的散列散列值。

【讨论】:

    【解决方案2】:

    哈希码可以是非唯一的。哈希冲突是生活中的现实,实现应该能够处理。

    您正在寻找的更多是国家的代表。这个谜题的一个状态是数字 0(?表示空)、1-8 的排列。因此,您正在寻找排列的唯一数字表示。

    这将被称为 Lehmer 代码:

    https://en.wikipedia.org/wiki/Permutation#Numbering_permutations

    理论讲了这么多,但你如何实现呢?这是一个建议的算法:

    https://www.researchgate.net/figure/The-Lehmer-code-A-complete-translation-from-permutation-to-decimal-by-way-of-the_fig1_230831447

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-17
      • 2020-07-25
      • 1970-01-01
      • 2019-10-04
      • 2019-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多