在O(n)中查找列表中包含所有成员的最大间隔

Jay*_*ram 40 algorithm logic

我在接受采访时被问到这个问题.给定一个整数列表,我们如何找到给定列表中所有成员的最大间隔?

例如,给出列表1,3,5,7,4,6​​,10然后回答是[3,7].因为它具有3到7之间的所有元素.

我试着回答,但我没有说服力.我采取的方法是先对列表进行排序,然后检查最大间隔.但我被要求这样做O(n).

Gri*_*yan 35

我知道基于散列和动态编程的解决方案.设f(x)为散列函数.诀窍是哈希表值.考虑列表中包含最长间隔,该间隔以x开头或结尾.然后h [ f(x) ] = y,其中y该区间的另一端.请注意,该间隔的长度将为abs(x-y)+ 1.算法描述将清楚说明存储该值的原因.

移动列表.设I为当前索引,x:= list [ i ] - 当前数字.现在

1.如果h [ f(x) ]不为空,那么我们之前已经遇到过数字x.无所事事,继续.

2.检查h [ f(x-1) ]h [ f(x + 1) ].

2.1.如果它们都不是空的,那意味着我们已经遇到了x-1x + 1,我们知道了一些间隔[ a..x-1 ][ x + 1..b ]我们已经在列表中见过面.我们知道,因为一个 = H [ F(X-1) ]b = H [ F(X + 1) ]通过定义ħ.现在当我们得到x时,这意味着我们现在已经满足了整个区间[ a,b ],所以我们更新如下值:h [ f(a) ]:= b h [f(b)]:= a.
同时将h [ f(x) ]设置为某个值(让我们说x,而不是影响答案),只是为了下次我们在列表中遇到x时,我们忽略它.x已经完成了他的工作.

2.2.如果只设置其中一个,那么假设h [ f(x-1) ] = a,这意味着我们已经遇到了一些区间[ a..x-1 ],现在它用x扩展.更新将是h [ f(a) ]:= xh [ f(x) ]:= a.

2.3.如果它们都没有设置,那意味着我们既没有遇到x-1,也没有遇到x + 1,而且我们已经遇到的包含x的最大区间是单个[ x ]本身.所以设h [ f(x) ]:= x.

最后,为了得到答案,传递整个列表并为所有x最大 abs(x - h [ f(x) ])+ 1.


Evg*_*uev 8

如果不希望排序,可以使用散列映射和Disjoint-set数据结构的组合.

对于列表中的每个元素,创建一个节点并使用key = element的值将其插入到哈希映射中.然后查询哈希映射的值+ 1和值-1.如果找到任何内容,请将当前节点与相邻节点所属的集合组合.完成列表后,最大集合对应最大间隔.

时间复杂度为O(N*α(N)),其中α(N)是逆Ackermann函数.

编辑:实际上,Disjoint-set对于这个简单的任务来说太强大了.Grigor Gevorgyan的解决方案不使用它.所以它更简单,更有效.

  • 我试图说可以生成输入来攻击哈希函数(或者访谈者可以将哈希视为冲突的主题).无论如何+1为实际可接受的解决方案. (2认同)

Dav*_*ave 5

您可以通过权衡空间来获得线性时间.

  1. 扫描列表中的最小值和最大值S和L.
  2. 使用布尔数组或位向量A,大到足以容纳(L - S + 1)条目.
  3. 再次浏览列表,在看到它时将A的相应元素设置为true.
  4. 现在,A已排序.通过A并找到最大的连续真值集.

列表中的第一步是线性的.最后一个是A的大小是线性的,如果你只有一些相距很远的值,它可能相对于你的列表很大.但是,既然你正在处理整体,那么A是有限的.


Too*_*eey -1

我想我会把它们排序到连续整数的列表中(假设每个数字只能出现一次)

取第一个数字

如果数字比现有列表中的数字低 1 或高 1?

是:在现有列表之前/之后

no :创建一个以当前号码开头的新列表

如果还有更多数字,则返回顶部

显示最长的列表