分而治之检查重复项

Posted

技术标签:

【中文标题】分而治之检查重复项【英文标题】:Checking duplicates with divide and conquer 【发布时间】:2015-05-30 18:56:56 【问题描述】:

为了在 nlogn 中搜索重复项,我决定使用修改后的合并排序。 主要问题是出现错误,我不知道如何解决这个问题:结果有时完全错误。

如果找到一对(具有相同值的元素),我的算法必须返回 True,如果没有一对,则返回 False。所有这些都必须在分治算法中完成。(没有额外的 for 循环 ecc。)

这是代码

def check_duplicates(X):   
    if len(X)>1:
        mid = len(X)//2
        lefthalf = X[:mid]
        righthalf = X[mid:]

        check_duplicates(lefthalf)
        check_duplicates(righthalf)

        i=0
        j=0
        k=0
        while i<len(lefthalf) and j<len(righthalf):
            if lefthalf[i] == righthalf[j]:
                return True

            if lefthalf[i]<righthalf[j]:
                X[k]=lefthalf[i]
                i=i+1
            else:
                X[k]=righthalf[j]
                j=j+1
            k=k+1

        while i<len(lefthalf):
            X[k]=lefthalf[i]
            i=i+1
            k=k+1

        while j<len(righthalf):
            X[k]=righthalf[j]
            j=j+1
            k=k+1

   return False

让我们举几个例子: 让X=[1,2,3]函数返回false,就可以了。 让X=[1,3,2]函数返回false,也可以。

主要问题在于这种情况:

X=[1,3,3]函数返回false,这是错误的(应该返回true)。

X=[4,6,6]函数返回false,错误等等。

主要问题是当我将两个相同的值放在列表末尾时,我不知道如何解决它......

ps:我为我的英语道歉

【问题讨论】:

所以,基本上这是一个合并排序,它还检查合并部分是否有重复项? 是的...但是当两个相同的值位于列表末尾时会出现问题.. 如果these numbers 是正确的,我认为你可以使用len(set(X)) != len(X) 在O(N) 中做到这一点 @Matt 我们不能使用集合...只是数组和基本操作... 【参考方案1】:

您忘记了,如果您进行递归调用,并且调用结果为True,那么也将返回True:因此,将递归调用修改为:

if(check_duplicates(lefthalf)) :
    return True

或完整(缩进)版本为:

def check_duplicates(X):   
    if len(X)>1:
        mid = len(X)//2
        lefthalf = X[:mid]
        righthalf = X[mid:]
        if(check_duplicates(lefthalf)) :
            return True
        if(check_duplicates(righthalf)) :
            return True
        i=0
        j=0
        k=0
        while i<len(lefthalf) and j<len(righthalf) :
            if lefthalf[i] == righthalf[j]:
                return True
            if lefthalf[i]<righthalf[j]:
                X[k]=lefthalf[i]
                i=i+1
            else:
                X[k]=righthalf[j]
                j=j+1
            k=k+1

        while i<len(lefthalf):
            X[k]=lefthalf[i]
            i=i+1
            k=k+1

        while j<len(righthalf):
            X[k]=righthalf[j]
            j=j+1
            k=k+1

    return False

在 while 循环中,您只检查交叉相等(两个子列表中的相等元素)。但是只有在***比较中return Trues 时才会返回您版本中的结果。

换句话说,您忘记在调用堆栈中传播True 值。

【讨论】:

感谢您的帮助,无论如何使用您的代码,它总是返回 True,因为由于合并排序是递归的,所以它总是调用 check_duplicates(lefthalf)check_duplicates(righthalf)。我试过X = [1,4],它返回True,这是错误的。有什么想法吗? @Bioshock:我已经对其进行了测试,它返回False,请确保保留缩进。它不会总是返回True。例如,具有一个元素的列表总是返回 False

以上是关于分而治之检查重复项的主要内容,如果未能解决你的问题,请参考以下文章

汉诺塔问题——分而治之(引入递归,解决重复子问题)

动态规划和分而治之

使用分而治之找到最长的递增子序列

分而治之算法 - 二分搜索变体

SIGABRT(信号 6)在使用分而治之的数组中查找多数元素时出错

深入浅出:快速排序