给定一个数字只能包含1到8(无重复)的数字,并且长度为8,如何在不使用hashSet
的情况下哈希这些数字?
由于程序的堆栈大小受到限制,我们不能直接使用哈希值个数的值。 (通过这个,我的意思是我们不能直接使数组的索引代表我们的数字)。
因此,此8位数字最多需要映射为5位数字。
我看到了this的答案。 hash
函数针对8位数字的输入返回8位数字。
那么,我在这里可以做什么?
答案 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位数哈希值(低于40320)。我在自行制定算法来执行此操作时遇到了一些麻烦,因此我做了一些挖掘工作。我发现这个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)
。二维的第一个索引表示数字从较小的数字开始,第二个索引表示数字从较大的数字开始。