多数元素Python

时间:2016-04-28 05:33:34

标签: python algorithm python-3.x divide-and-conquer

我无法在我的“Majority Element”中获得正确的输出并在Python 3中征服算法实现。

这应该是相对正确的;然而,我似乎仍然缺少一些东西或稍微偏离了我无法弄清楚为什么会这样。

我尝试了一些调试语句和不同的东西。它看起来像在代码上面的注释中列出的特定情况,它为“left_m”解析-1,在执行递归调用时解析为“right_m”的941795895。当它将每个索引处的元素与这些变量进行比较时,计数器显然永远不会递增。

我是以错误的方式来做这件事的吗?任何帮助将不胜感激。

感谢。

# Input:
# 10
# 2 124554847 2 941795895 2 2 2 2 792755190 756617003
# Your output:
# 0
# 
# Correct output:
# 1

def get_majority_element(a, left, right):
 if left == right:
     return -1
 if left + 1 == right:
     return a[left]

 left_m = get_majority_element(a, left, (left + right - 1)//2)
 right_m = get_majority_element(a, (left + right - 1)//2 + 1, right)

 left_count = 0
 for i in range(0, right):
     if a[i] == left_m:
         left_count += 1
 if left_count > len(a)//2:
     return left_m

 right_count = 0
 for i in range(0, right):
     if a[i] == right_m:
         right_count += 1
 if right_count > len(a)//2:
     return right_m

 return -1

if __name__ == '__main__':
    input = sys.stdin.read()
    n, *a = list(map(int, input.split()))
    if get_majority_element(a, 0, n) != -1:
        print(1)
    else:
        print(0)

2 个答案:

答案 0 :(得分:7)

在计算左右主要元素的外观时,循环会超出范围(0,右)。相反,他们应该越过范围(左,右)。从0开始可能会导致在较小的子问题中返回不正确的主要元素。

此外,除了for循环覆盖范围内的起始索引不正确的问题之外,你的递归调用参数似乎也有问题,可能是由于你的直觉导致你忽略了一些细节。在整个get_majority_element函数中,您将参数 right 视为不在列表中的第一个索引,而不是 right 是列表中最右侧元素的索引。

但是,在第一次递归调用中,您将第三个参数视为该列表中的最后一个元素包含。如果right是不在该列表中的第一个元素的索引,则它实际上应与您在下一行中进行的第二个递归调用的第二个参数相同。所以,你正在制作的第一个递归调用的第三个参数小于它应该是1,导致你每次递归地忽略1个元素

第三,在for循环之后的if语句中有一个错误,类似于循环范围的问题。您正在为所有len(a)元素划分元素的出现,尽管您应该只关心当前正在处理的子问题。因此,您应该将其除以该子问题中的元素数,而不是len(a)。 (即(右 - 左)// 2)

您可以在下方找到工作代码,并查看here以观察其执行情况。

def get_majority_element(a, left, right):
    if left == right:
        return -1
    if left + 1 == right:
        return a[left]

    left_m = get_majority_element(a, left, (left + right - 1)//2 + 1)
    right_m = get_majority_element(a, (left + right - 1)//2 + 1, right)
    left_count = 0
    for i in range(left, right):
        if a[i] == left_m:
            left_count += 1
    if left_count > (right-left)//2:
        return left_m

    right_count = 0
    for i in range(left, right):
        if a[i] == right_m:
            right_count += 1
    if right_count > (right-left)//2:
        return right_m

    return -1

if __name__ == '__main__':
    input = sys.stdin.read()
    n, *a = list(map(int, input.split()))
    print("n=" + str(n))
    if get_majority_element(a, 0, len(a)) != -1:
        print(1)
    else:
        print(0)

答案 1 :(得分:0)

我正在尝试使用Boyers和Moore的算法来查找列表中的多数元素。我正在使用内置函数,count;因此,如果多数元素大于列表的一半大小,那么它给出输出1,否则为0.您可以在此链接中找到更多关于Boyers和Moore的算法以查找多数Algorithm information here

# Uses python3
import sys

def get_majority_element(a,n):
    maximum = a[0]
    amount = 1
    for i in (a[1:]):
        if not  maximum == i:
            if amount >= 1:
                amount = amount - 1
            else:
                maximum = i
                amount = 1
        else:
            amount = amount + 1
    output = a.count(maximum)
    if output > n//2:
        return 1
    return 0



if __name__ == '__main__':
    input = sys.stdin.read()
    n, *a = list(map(int, input.split()))
    print (get_majority_element(a,n))