任务显然是找到在所需数字列表的长度N中为O(1)的算法。因此,不管您需要前100个数字还是10000个数字,插入时间都应为O(1)。
这里的诀窍是,尽管列表插入提到了O(1)要求,但问题没有说出整数空间中搜索时间的顺序,但是事实证明可以将其设为O(1)也一样 然后的解决方案如下:
安排一个哈希表,其中键的数字为数字,值的链接列表指针为一对。每对指针是链接列表序列的开始和结束。通常这只是一个元素,然后是下一个。链表中的每个元素都位于编号第二高的元素旁边。因此,链表包含所需编号的排序顺序。保留最低编号的记录。
从随机流中获取一个新的数字x。
是否高于最后记录的最低数字?是=>步骤4,否=>步骤2
用刚刚取得的数字点击哈希表。有条目吗?是=>步骤5。否=>取一个新的数字x-1并重复此步骤(这是一个简单的向下线性搜索,请耐心等待,这可以改进,我将解释如何做)
使用刚刚从哈希表中获得的list元素,在链接列表中的该元素之后插入新数字(并更新哈希)
取记录的最低数字l(并将其从哈希/列表中删除)。
用刚刚取得的数字点击哈希表。有条目吗?是=>步骤8。否=>取一个新的数字l + 1并重复此步骤(这是一个简单的向上线性搜索)
命中数为正时,该数字将成为新的最低数字。前往步骤2
为了允许重复的值,散列实际上需要维护链表中重复项的开始和结束。因此,在给定键处添加或删除元素会增加或减小指向的范围。
这里的插入是O(1)。我猜提到的搜索是O(数字之间的平均差)。平均差随数字空间的大小而增加,但随数字列表的所需长度而减小。
因此,如果数字空间很大(例如,对于4字节的int类型,0到2 ^ 32-1)并且N = 100,则线性搜索策略非常差。要解决此性能问题,您可以保留并行的哈希表集,在哈希表中将数字四舍五入到更高的幅度(例如1s,10s,100s,1000s)以创建合适的密钥。这样,您可以提高和降低齿轮速度,以更快地执行所需的搜索。我认为性能然后变为O(log numberrange),它是恒定的,即也为O(1)。
为了使这一点更清楚,假设您手头有197。您用“ 190”打了一个10s哈希表,将其四舍五入到最接近的十。有什么事吗 不。因此,您在10秒钟内下降,直到您说出120。然后您可以从1s哈希表中的129开始,然后尝试128、127,直到您击中某些东西。现在,您已经在链接列表中的何处插入了数字197。在将其插入时,还必须使用197条目更新1s哈希表,将数字190更新为10s哈希表,将100替换为100,以此类推。大多数步骤您曾经要做的是数字范围的10倍的对数。
我可能错了一些细节,但是由于这是程序员的交流,而上下文是访谈,所以我希望以上内容可以为这种情况提供一个令人信服的答案。
编辑我在这里添加了一些额外的详细信息来解释并行哈希表方案,以及它如何表示可以用O(1)搜索代替我提到的不良线性搜索。我也意识到当然不需要搜索下一个最低编号,因为您可以通过查找具有最低编号的哈希表并前进到下一个元素来直接进入该编号。