当前位置: 首页 > 知识库问答 >
问题:

求最大子数组的分治算法-如何也提供结果子数组索引?

贝嘉泽
2023-03-14

对不起,我有一个任务要用蛮力算法O(n^2)、分治算法O(nlogn)和Kadane算法O(n)来解决最大子数组问题。(我的代码不同)。

#include <iostream>

int DivideAndConquer(int[], int);

int main()
{
    // Example 1
    //const int MyArraySize = 16;
    //int MyArray[MyArraySize] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7 }; // answer: Index 7 -> 10, sum = 43

    // Example 2
    const int MyArraySize = 8;
    int MyArray[MyArraySize] = { -2, -5, 6, -2, -3, 1, 5, -6 }; // answer: Index 2 -> 6, sum = 7

    int FinalResult;

    FinalResult = DivideAndConquer(MyArray, MyArraySize);
    std::cout << "Using Divide And Conquer: With O(nlogn) Sum = " << FinalResult << "\n\n";

    system("pause");
    return 0;
}

int DivideAndConquer(int* _myArray, int _myArraySize)
{
    if (_myArraySize == 1)
        return _myArray[0];

    int middle = _myArraySize / 2;
    int Result_LeftPortion = DivideAndConquer(_myArray, middle);
    int Result_RightPortion = DivideAndConquer(_myArray + middle, _myArraySize - middle);

    int LeftSum = -9999;
    int RightSum = -9999;
    int TotalSum = 0;

    for (int i = middle; i < _myArraySize; i++)
    {
        TotalSum += _myArray[i];
        RightSum = TotalSum < RightSum ? RightSum : TotalSum;
    }

    TotalSum = 0;

    for (int i = middle - 1; i >= 0; i--)
    {
        TotalSum += _myArray[i];
        LeftSum = TotalSum < LeftSum ? LeftSum : TotalSum;
    }

    int PartialResult = LeftSum < RightSum ? RightSum : LeftSum;
    int Result= (PartialResult < LeftSum + RightSum ? LeftSum + RightSum : PartialResult);

    return Result;
}

共有1个答案

岳佐
2023-03-14

你的算法有逻辑问题,它不是最优的。您甚至没有使用result_leftpartesresult_rightpartes值。最终结果始终是整个数组的rightsumleftsumtotalsum的最大值。所有其他子数组的值将被忽略。

用分而治之的方法解决这个问题的方法如下。应该为每个子数组保存四个值:

  1. 包含左元素(s_l)的最大和
  2. 包含正确元素(s_r)的最大和
  3. 整个数组(t)的和
  4. 以上值的最大值(mx)
    null
sub_left.s_r range is (2,5)
sub_right.t range is (6,10)
if ( sub_right.t + sub_left.s_r > sub_right.s_r )
      s_r range = (2,10)

这是我的实现:

#include <iostream>
using namespace std;

struct node {
    //value, right index, left index
    int value,  r,  l;
    node(int _v, int _r, int _l){
        value = _v;
        r = _r;
        l = _l;
    }
    node (){}

};

struct sub {
    // max node containing left element
    // max node containing right element
    // total node
    // max node
    node s_l, s_r, t, mx;
    sub ( node _l, node _r, node _t, node _mx ){
        s_l = _l;
        s_r = _r;
        t = _t;
        mx = _mx;
    }
    sub(){}
};


sub DivideAndConquer(int* _myArray, int left, int right)
{

    if(right == left){
        node n (_myArray[left],right,left);
        return sub( n, n, n, n);
    }
    int mid = (left+right)/2;
    sub sub_left = DivideAndConquer( _myArray, left, mid);
    sub sub_right = DivideAndConquer( _myArray, mid+1, right);

    sub cur;
    if ( sub_left.t.value + sub_right.s_l.value > sub_left.s_l.value ){
        cur.s_l.value = sub_left.t.value + sub_right.s_l.value;
        cur.s_l.r = sub_right.s_l.r;
        cur.s_l.l = sub_left.s_l.l;
    } else {
        cur.s_l = sub_left.s_l;
    }

    if ( sub_right.t.value + sub_left.s_r.value > sub_right.s_r.value ){
        cur.s_r.value = sub_right.t.value + sub_left.s_r.value;
        cur.s_r.l = sub_left.s_r.l;
        cur.s_r.r = sub_right.s_r.r;
    } else {
        cur.s_r = sub_right.s_r;
    }

    cur.t.value = sub_right.t.value + sub_left.t.value;
    cur.t.r = sub_right.t.r;
    cur.t.l = sub_left.t.l;

    if ( cur.s_r.value >= cur.s_l.value &&
         cur.s_r.value >= cur.t.value &&  
         cur.s_r.value >= sub_left.mx.value &&
         cur.s_r.value >= sub_right.mx.value ){
        cur.mx = cur.s_r;
    } else if ( cur.s_l.value >= cur.s_r.value &&
         cur.s_l.value >= cur.t.value &&  
         cur.s_l.value >= sub_left.mx.value &&
         cur.s_l.value >= sub_right.mx.value ){
        cur.mx = cur.s_l;
    } else if ( sub_left.mx.value >= cur.s_l.value &&
         sub_left.mx.value >= cur.t.value &&  
         sub_left.mx.value >= cur.s_r.value &&
         sub_left.mx.value >= sub_right.mx.value ){
        cur.mx = sub_left.mx;
    } else {
        cur.mx = sub_right.mx;
    }

    if ( sub_left.s_r.value + sub_right.s_l.value > cur.mx.value ){
        cur.mx.value = sub_left.s_r.value + sub_right.s_l.value;
        cur.mx.l = sub_left.s_r.l;
        cur.mx.r = sub_right.s_l.r;
    }
    return cur;
}

int main()
{
    // Example 1
    //const int MyArraySize = 16;
    //int MyArray[MyArraySize] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7 }; // answer: Index 7 -> 10, sum = 43

    // Example 2
    const int MyArraySize = 8;
    int MyArray[MyArraySize] = { -2, -5, 6, -2, -3, 1, 5, -6 }; // answer: Index 2 -> 6, sum = 7

    sub FinalResult = DivideAndConquer(MyArray, 0,MyArraySize-1);
    std::cout << "Sum = " << FinalResult.mx.value << std::endl;
    std::cout << "( " << FinalResult.mx.l << " , " << FinalResult.mx.r << ")" << std::endl;

 //   system("pause");
    return 0;
}

注意:此算法在O(n)时间内运行。

 类似资料:
  • 对于使用分治方法的最大和子数组算法,我需要返回和和子数组。 我能在所有的测试中正确地计算和。然而,我无法计算出正确的子数组。 我的总数(正确):34 阵列:2 9 8 6 5-11 9-11 7 5-1-8-3 7-2 正确子数组:2 9 8 6 5 我的总数(正确):50 阵列:31-41 59 26-53 58 97-93-23 84 正确子数组:59 26-53 58 97 我的总数(正确)

  • 免责声明:我知道这个问题可以通过数组的单次传递非常有效地解决,但我对用分而治之法做这个很感兴趣,因为它与我们用分而治之法处理的典型问题有点不同。 假设给定一个浮点数组x[1:n],大小为n,间隔长度为l。问题是设计一个分治算法,从具有最大和的数组中找到长度为l的子数组。 现在,为了将问题分成两半,我决定在n-l+1/2处中断数组,以便将相等数量的子数组分配到我的除法的两半,如下面的算法所示。同样,

  • 本文向大家介绍在C ++中使用分而治之算法的最大子数组总和,包括了在C ++中使用分而治之算法的最大子数组总和的使用技巧和注意事项,需要的朋友参考一下 假设我们有一个带有正值和负值的数据列表。我们必须找到其总和最大的连续子数组的总和。假设列表包含{-2,-5,6,-2,-3,1,5,-6},则最大子数组的总和为7。它是{6,-2,-3的总和,1,5} 我们将使用分而治之方法解决此问题。步骤如下所示

  • 今年Spring我为一家IT公司写了实习入学考试。下面描述了一个问题。我不能解决它,所以我需要帮助(目前我要通过新的测试,所以我需要分析我的错误)。我很乐意为你效劳。 输入:一个数组arr,N个整数,arr的N个长度,数字K(K 对于offset的所有容许值,求s_arr(offset)的最小元素 算法复杂度应小于O(n*k) 输出:所有对(偏移量,最小(s_arr(偏移量)) 我的微不足道的解决

  • 我试图在一个数组中找到具有最大和的邻接子数组。所以,对于数组 {5,15,-30,10,-5,40,10}