使用分而治之的方法从给定列表中查找第二个最小的数字

时间:2013-10-16 23:38:30

标签: algorithm math

我正在努力解决这个问题..

  

给定n个数字列表,我们希望找到最小和最小的数字   列表中的数字。描述一种分而治之的算法来解决这个问题。假设对于整数k,n = 2 ^ k。使用算法的比较次数应该是   即使在最坏的情况下也不会超过3n / 2 - 2。

我目前的解决方案是使用选择算法来获得中位数,然后将列表分成L1(包含小于或等于中位数的元素),R(中位数),L2(包含比中位数更大的所有元素)。这是对的吗?如果是这样,我接下来应该做什么?

2 个答案:

答案 0 :(得分:9)

请注意,中值选择算法使用Θ(n)比较,但这并不意味着它最多使用3n / 2 - 2比较。事实上,我认为它使用了更多,这可能会排除您的解决方案策略。

作为提示:将此问题视为为所有2 k构建淘汰赛;每轮的获胜者(两个数字中较小的一个)前进到下一轮。需要多少次比较才能实现?接下来,请注意第二小数字必须“丢失”到最小数字。第二小数字也是“丢失”到最小数字的最小数字。鉴于此,您能否有效地找到第二小的数字?

希望这有帮助!

答案 1 :(得分:3)

哦,我只是理解它(在Python中):

def two_min(arr):
    n = len(arr)
    if n==2: # Oops, we don't consider this as comparison, right?
        if arr[0]<arr[1]:                   # Line 1
            return (arr[0], arr[1])
        else:
            return (arr[1], arr[0])
    (least_left, sec_least_left) = two_min(arr[0:n/2])
    (least_right, sec_least_right) = two_min(arr[n/2:])
    if least_left < least_right:            # Line 2
        least = least_left
        if least_right < sec_least_left:    # Line 3
            return (least, least_right)
        else:
            return (least, sec_least_left)
    else:
        least = least_right
        if least_left < sec_least_right:    # Line 4
            return (least, least_left)
        else:
            return (least, sec_least_right)

总计:

第1行:将进行确切的n/2比较

第2行:此处将进行n/4 + n/8 + ... + 1次比较

第3行和第4行:每次调用two_min时都会执行其中一个(除非使用两个元素调用它)。我们总共two_minn-1次呼叫(因为有很多锦标赛),其中n/2被调用两个元素。因此,第3行和第4行有助于n/2 - 1比较

结合所有这些,我们有:

total_comparisons = n/2 + (n/4 + n/8 + ... + 1) + (n/2 - 1)
                  = (n - 1) + (n/2 - 1)
                  = 3n/2 - 2
相关问题