散列8位数字,该数字只能包含1到8之间的非重复数字

时间:2018-09-06 18:20:23

标签: hash hashset

给定一个数字只能包含1到8(无重复)的数字,并且长度为8,如何在不使用hashSet的情况下哈希这些数字?

由于程序的堆栈大小受到限制,我们不能直接使用哈希值个数的值。 (通过这个,我的意思是我们不能直接使数组的索引代表我们的数字)。

因此,此8位数字最多需要映射为5位数字。

我看到了this的答案。 hash函数针对8位数字的输入返回8位数字。

那么,我在这里可以做什么?

2 个答案:

答案 0 :(得分:2)

您可以做一些事情。您可以从每个数字中减去1并将其解析为一个八进制数字,该数字将域中的每个数字一一对应到[0,16777216)范围。所得的数字可用作很大数组的索引。这样的一个示例可能如下所示:

function hash(num) {
  return parseInt(num
    .toString()
    .split('')
    .map(x => x - 1), 8);
}

const set = new Array(8**8);
set[hash(12345678)] = true;
// 12345678 is in the set

或者,如果您想节省一些空间并在添加元素时扩大数据结构。您可以使用每个节点有8个分支,最大深度为8的树形结构。如果您认为值得这样做,我将由您自己决定。


修改: 看到更新后的问题后,我开始考虑如何将数字映射到按字母顺序排序的1-8位数字排列列表中的位置。这将是最佳选择,因为它为您提供了所需的理论5位数哈希值(低于403​​20)。我在自行制定算法来执行此操作时遇到了一些麻烦,因此我做了一些挖掘工作。我发现这个example implementation可以满足您的需求。我从中得到了启发,可以为您实现JavaScript算法。

function hash(num) {
  const digits = num
    .toString()
    .split('')
    .map(x => x - 1);
  const len = digits.length;
  const seen = new Array(len);
  let rank = 0;

  for(let i = 0; i < len; i++) {
    seen[digits[i]] = true;
    rank += numsBelowUnseen(digits[i], seen) * fact(len - i - 1);
  }

  return rank;
}

// count unseen digits less than n
function numsBelowUnseen(n, seen) {
  let count = 0;
  for(let i = 0; i < n; i++) {
    if(!seen[i]) count++;
  }
  return count;
}

// factorial fuction
function fact(x) {
  return x <= 0 ? 1 : x * fact(x - 1);
}

答案 1 :(得分:0)

kamoroso94使我想到了以八进制表示数字。如果我们从中删除第一个数字,该数字将保持唯一。因此,我们可以创建一个长度为8^7=2097152的数组,从而使用7位数的八进制版本作为索引。

如果此数组的大小大于堆栈的大小,则我们只能使用输入的6位数字,并将其转换为八进制值。因此,8^6=262144很小。我们可以制作一个长度为8^6的2D数组。因此,使用的总空间约为2*(8^6)。二维的第一个索引表示数字从较小的数字开始,第二个索引表示数字从较大的数字开始。

相关问题