在大小为n * k + b的数组中找到b次发生的元素

时间:2012-02-25 09:49:54

标签: arrays algorithm

描述

给定一个大小为(n*k+b)的数组,其中n个元素出现k次,一个元素出现b次,换句话说,有n+1个不同的元素。鉴于0 < b < k发现元素出现了b次。

我尝试的解决方案

  1. 明显的解决方案是使用散列,但如果数字非常大则不起作用。复杂性为O(n)

  2. 使用map存储每个元素的频率,然后遍历map以查找出现b次的元素。由于Map的实现为高度平衡树,复杂性将为O(nlogn)

  3. 我的两个解决方案都被接受但是面试官想要一个线性解决方案,而不使用散列和暗示他给出的树的高度在你存储频率的树中保持不变,但我无法弄清楚正确的解决方案爱好。

    我想知道如何在没有散列的线性时间内解决这个问题?

    编辑:

    样品:

    输入:n=2 b=2 k=3

    Aarray:2 2 2 3 3 3 1 1

    输出:1

5 个答案:

答案 0 :(得分:11)

我假设:

  1. 阵列的元素具有可比性。
  2. 我们事先知道n和k的值。
  3. 解决方案O(n * k + b)足够好。
  4. 让数字仅出现b次。我们试图在n * k + b大小的数组中找到S.

    递归步骤:查找当前数组切片的中间元素,如同在线性时间中快速排序一样。设中位元素为M.

    在递归步骤之后,你有一个数组,其中所有小于M的元素出现在M的第一个出现的左边。所有M个元素彼此相邻,所有大于M的元素都在所有出现的元素的右边。 M.

    查看最左边的M的索引并计算S&lt; M或S&gt; = M。递归在左切片或右切片上。

    所以你正在进行快速排序,但是随时只钻研部门的一部分。您将递归O(logN)次,但每次都使用原始数组的1 / 2,1 / 4,1 / 8,...大小,因此总时间仍为O(n)。

    澄清:假设n = 20且k = 10.然后,阵列中有21个不同的元素,其中20个发生10次,最后发生7次。我找到了中等元素,假设它是1111.如果S <1111比最左边出现的1111的指数小于11 * 10。如果S> = 1111则索引将等于11 * 10.

    完整示例: n = 4. k = 3.数组= {1,2,3,4,5,1,2,3,4,5,1,2,3, 5} 在第一个递归步骤之后,我发现中间元素是3,数组是这样的:{1,2,1,2,1,2,3,3,3,5,4,5,5,4} 3. 3左边的6个元素是k = 3的倍数。所以每个元素必须在那里发生3次。所以S&gt; = 3。递归右侧。等等。

答案 1 :(得分:9)

使用循环群的想法。

要猜测第i位答案,请按照以下步骤操作:

  1. 计算数组中第i位设置的数量,存储为cnt
  2. 如果cnt % k非零,则设置第i位答案。否则很清楚。
  3. 要猜测整数,请对每一位重复上述步骤。

    此解决方案在技术上O((n*k+b)*log max N),其中max N是表中的最大值,但由于位数通常是常量,因此此解决方案在数组大小上是线性的。

    没有散列,内存使用量为O(log k * log max N)

    示例实施:

    from random import randint, shuffle
    
    def generate_test_data(n, k, b):
        k_rep = [randint(0, 1000) for i in xrange(n)]
        b_rep = [randint(0, 1000)]
        numbers = k_rep*k + b_rep*b
        shuffle(numbers)
        print "k_rep: ", k_rep
        print "b_rep: ", b_rep
        return numbers
    
    def solve(data, k):
        cnts = [0]*10
        for number in data:
            bits = [number >> b & 1 for b in xrange(10)]
            cnts = [cnts[i] + bits[i] for i in xrange(10)]
        return reduce(lambda a,b:2*a+(b%k>0), reversed(cnts), 0)
    
    print "Answer: ", solve(generate_test_data(10, 15, 13), 3)
    

答案 2 :(得分:4)

为了使包含n个不同元素的 B-tree 具有恒定高度,且h高度不变,每个节点需要z=n^(1/h)个子项:{ {1}},因此h=log_z(n)h=log(n)/log(z)log(z)=log(n)/hz=e^(log(n)/h)z=n^(1/h)

示例,n=1000000h=10z=3.98,即z=4

在这种情况下,到达节点的时间是O(h.log(z))。假设hz为“常数”(自N=n.k起,然后log(z)=log(n^(1/h))=log(N/k^(1/h))=ct通过h正确选择k,则可以说O(h.log(z))=O(1) ......这有点牵强,但这可能就是采访者想要听到的那种?

答案 3 :(得分:2)

更新:这个使用哈希,所以这不是一个好的答案:(

在python中

这将是线性时间(set将删除重复项):

result = (sum(set(arr))*k - sum(arr)) / (k - b)

答案 4 :(得分:0)

如果'k'是偶数且'b'是奇数,则XOR将执行。 :)