使用分治算法在未排序的数组中查找最大和

Posted

技术标签:

【中文标题】使用分治算法在未排序的数组中查找最大和【英文标题】:Finding largest sum in an unsorted array using divide and conquer algorithm 【发布时间】:2017-01-19 09:15:23 【问题描述】:

我有一个包含 n 个实数的序列,存储在一个数组 A[1]、A[2]、...、A[n] 中。我正在尝试实现一个分而治之的算法来找到两个数字 A[i] 和 A[j],其中 i

例如。 2, 5, 9, 3, -2, 7 将给出 14 的输出(5+9,而不是 16=9+7)。谁能给我一些关于如何做的想法?

提前致谢。

【问题讨论】:

还有你打算用什么语言来做这个。这是python中的三行:) 是什么让您认为“分而治之”是正确的做法? 预期的复杂性是多少? O(nlgn)? 还有 5,4,3,2,1 的答案是什么? 在这里发布以供后代使用jsbin.com/cameci/5/edit?js,console 但我对此不太满意,也不确定其复杂性 【参考方案1】:

这个问题并不真正适合分而治之的方法。 很容易观察到,如果 (i, j) 是这个问题的解决方案,那么 A[j] >= A[k] 对于每个k > j,即A[j]是A[j..n]中的最大值

证明:如果存在这样的k > j且A[k] > A[j],那么(j, k)是比(i, j)更好的解

所以我们只需要考虑满足该标准的js。

算法(伪代码)

maxj = n
for (j = n - 1 down to 1):
  if (a[j] > a[maxj]) then:
    maxj = j
  else:
    check if (j, maxj) is a better solution

复杂度:O(n) C++实现:http://ideone.com/ENp5WR(实现使用整数数组,但浮点数应该一样)

【讨论】:

j 在 i 的循环中从何而来? 那么我认为现在证明是正确的,虽然它不是 OP 中要求的 D&C,但仍然赞成干净的解决方案【参考方案2】:

声明两个变量,在算法期间检查当前数字是否大于当前存储在变量中的两个值中的任何一个,如果是则替换最小的,如果不是,继续。

【讨论】:

这是一个如何“分而治之”的算法? 它将一组数字分解成一个简单的数字更大【参考方案3】:

这是 Python 中的递归解决方案。我不会完全称其为“分而治之”,但话说回来,这个问题不太适合分而治之的方法。

def recurse(lst, pair):             # the remaining list left to process
    if not lst: return              # if lst is empty, return
    for i in lst[1:]:               # for each elements in lst starting from index 1
        curr_sum = lst[0] + i   
        if lst[0] < i and curr_sum > pair[0]+pair[1]:  # if the first value is less than the second and curr_sum is greater than the max sum so far
            pair[0] = lst[0]
            pair[1] =  i        # update pair to contain the new pair of values that give the max sum
    recurse(lst[1:], pair)          # recurse on the sub list from index 1 to the end 

def find_pair(s):
    if len(s) < 2: return s[0]
    pair = [s[0],s[1]]      # initialises pair array
    recurse(s, pair)    # passed by reference
    return pair

样本输出:

s = [2, 5, 9, 3, -2, 7]
find_pair(s)     #       ============> (5,9) 

【讨论】:

您的算法会为 1,7,5,6 生成什么? @serhiyb 它产生 [5,6]。你可以试试here。 你应该用 [-Infinity, -Infinity] 初始化,它是 O(n²) 是的,我明白了,但是你的复杂度是 O(n^2) 而作者正在寻找 O(n*log(n)) - 典型的分治复杂度。 @serhiyb 这不是一个适合分而治之的问题。你不能强迫一个问题遵循分而治之的策略;它需要有某种自我相似性。这是我能想到的最接近的。【参考方案4】:

我认为您可以使用O(n) 中的算法,如下所述

(合并部分使用常数时间)

这是算法的概要:

    将问题分为两半:LHS 和 RHS 每一半都应该返回满足那一半要求的最大答案AND那一半中最大的元素 合并并返回上层答案:答案是 LHS 的答案、RHS 的答案以及两半中最大元素之和的最大值(仅当 RHS 的最大元素 >= LHS 的最大元素时才考虑这个)

这是使用您的示例的算法演示:2, 5, 9, 3, -2, 7

    分为2,5,9、3,-2,7 分为2,5、9、3,-2、7 2,5 返回 max(2,5, 5+2) = 7,最大元素 = 5 9 返回 9,最大元素 = 9 3,-2 返回 max(3,-2) = 3,最大元素 = 3 7 返回 7,最大元素 = 7 2,5,9 从 2,5 & 9 合并:返回 max(7,9,9+5) = 14,最大元素 = max(9,5) = 9 3,-2,7 从 3,-2 & 7 合并:返回 max(3,7,7+3) = 10,最大元素 = max(7,3) = 7 2,5,9,3,-2,7 从 2,5,9 和 3,-2,7 合并:返回 max(14,10) = 14,最大元素 = max (9,7) = 9

ans = 14


像 5,4,3,2,1 这样没有答案的特殊情况需要额外处理,但不会影响核心部分和算法的复杂性。

【讨论】:

以上是关于使用分治算法在未排序的数组中查找最大和的主要内容,如果未能解决你的问题,请参考以下文章

分治法

算法——分治和快速排序

以下算法在未排序数组中找到最小值的复杂性

基础算法 分治法求最大最小元

使用分治技术的数组的最大公约数

分治法应用之二分查找 快速排序递归排序