我正在努力解决这个问题..
给定n个数字列表,我们希望找到最小和最小的数字 列表中的数字。描述一种分而治之的算法来解决这个问题。假设对于整数k,n = 2 ^ k。使用算法的比较次数应该是 即使在最坏的情况下也不会超过3n / 2 - 2。
我目前的解决方案是使用选择算法来获得中位数,然后将列表分成L1(包含小于或等于中位数的元素),R(中位数),L2(包含比中位数更大的所有元素)。这是对的吗?如果是这样,我接下来应该做什么?
答案 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_min
次n-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