找到未排序数组的主导模式

时间:2013-02-07 05:00:52

标签: c++ c algorithm recursion master-theorem

注意,这是一项家庭作业。

我需要找到数组的模式(正值),如果模式大于sizeof(array)/2(主导值),则返回该值。有些阵列没有。 这很简单,但是有一个限制,在确定之前不能对数组进行排序,此外,复杂性必须在O(nlogn)的数量级上。

使用这个第二个约束和master theorem,我们可以确定时间复杂度'T(n)= A * T(n / B)+ n ^ D',其中A = B和log_B(A) = D表示O(nlogn)为真。因此,A = B = D = 2。这也很方便,因为主导值必须在阵列的第一,第二或两半中占主导地位。

使用'T(n)= A * T(n / B)+ n ^ D'我们知道搜索函数会在每个级别调用自己两次(A),将每个级别设置的问题除以2( B)。我不知道如何让我的算法考虑到每个级别的n ^ 2。

制作一些代码:

int search(a,b) {
    search(a, a+(b-a)/2);
    search(a+(b-a)/2+1, b);
}

我在这里缺少的“胶水”是如何组合这些分开的功能,我认为这将实现n ^ 2的复杂性。这里有一些技巧,其中主导必须在第一或第二半中占主导地位,或两者兼而有之,不太确定这对于我现在如何通过复杂性约束来帮助我。

我已经写下了一些小数组的例子,并且我已经提出了它可以划分的方法。我似乎无法找到一个始终返回主导价值的单一方法。

在级别0,函数需要调用自身来搜索数组的前半部分和后半部分。这需要递归,并自行调用。然后在每个级别,它需要执行n ^ 2个操作。因此,在数组[2,0,2,0,2]中,它会将其拆分为[2,0]上的搜索和[2,0,2]上的搜索并执行25次操作。搜索[2,0]将调用[2]上的搜索并搜索[0]并执行4次操作。我假设这些需要搜索数组空间本身。我打算使用C ++并使用STL中的东西来迭代和计算值。我可以创建一个大型数组,只需按索引更新计数。

2 个答案:

答案 0 :(得分:2)

如果你想找到一个数组的主导模式,并递归地执行,这里是伪代码:

def DominantMode(array):
    # if there is only one element, that's the dominant mode
    if len(array) == 1: return array[0]
    # otherwise, find the dominant mode of the left and right halves
    left = DominantMode(array[0:len(array)/2])
    right = DominantMode(array[len(array)/2:len(array)])
    # if both sides have the same dominant mode, the whole array has that mode
    if left == right: return left
    # otherwise, we have to scan the whole array to determine which one wins
    leftCount = sum(element == left for element in array)
    rightCount = sum(element == right for element in array)
    if leftCount > len(array) / 2: return left
    if rightCount > len(array) / 2: return right
    # if neither wins, just return None
    return None

上述算法是O(nlogn)时间,但只有O(logn)空间。

如果要查找数组的模式(不仅仅是主导模式),首先要计算直方图。您可以在O(n)时间内完成此操作(通过将数组值映射到其频率的哈希表中存储历史记录,只需访问数组的每个元素一次)。

计算完直方图后,您可以迭代它(最多访问每个元素一次)以找到最高频率。一旦发现频率大于数组大小的一半,就可以立即返回并忽略直方图的其余部分。由于直方图的大小不能大于原始数组的大小,因此该步骤也是O(n)时间(和O(n)空间)。

由于两个步都是O(n)时间,因此算法复杂度为O(n)时间。

答案 1 :(得分:2)

如果某个数字超过一半,可以通过O(n)时间复杂度和O(1)空间复杂度来完成,如下所示:

int num = a[0], occ = 1;
for (int i=1; i<n; i++) {
    if (a[i] == num) occ++;
    else {
        occ--;
        if (occ < 0) {
            num = a[i];
            occ = 1;
        }
    }
}

因为你不确定是否会出现这样的数字,所以你需要做的就是先应用上面的算法得到一个数字,然后第二次迭代整个数组得到数字的出现并检查它是否大于一半。