现在的位置: 首页 > 综合 > 正文

最大子段和:线性序列的最大子段和的三种解法

2019年04月15日 ⁄ 综合 ⁄ 共 2464字 ⁄ 字号 评论关闭

 

//线性序列的最大子段和的三种解法

1. 蛮力法

int MaxSubSum1(int* arr, int n, int& iPos, int& jPos)

{

        int sum = 0;

        // i和j是子串的起始位置。

        for (int i = 0; i < n; ++i)

            for (int j = i; j < n; ++j)

            {

                int thisSum = 0;

                // 计算当前子串的长度。

                for (int k = i; k <=j; ++k)

                    thisSum += arr[k];

                // 更新目前为止最大子串的长度和最大子串的起始位置。

                if (thisSum > sum)

                {

                    sum = thisSum;

                    iPos = i;

                    jPos = j;

                }

            }

        return sum;

}

算法的改进:

int MaxSubSum2(int* arr, int n, int& iPos, int& jPos)

{

        int sum = 0;

        for (int i = 0; i < n; ++i)

        {

            int thisSum = 0;

            for (int j = i; j < n; ++j)

            {

                // 这样thisSum就能重复利用已经加起来的值,而不是每次都从零开始。

                thisSum += arr[j];

                if (thisSum > sum)

                {

                    sum = thisSum;

                    iPos = i;

                    jPos = j;

                }

            }

        }

        return sum;

}

2. 分治法:

int MaxSubSum3(int* arr, int left, int right)

{

        int sum = 0;

        // Small(P)

        if (left == right)

            sum = arr[left] > 0 ? arr[left] : 0;

        // If P is not small, divide P into subproblems.

        else

        {

            // Find where to split the set.

            int center = (left + right ) / 2;

            // Solve the subproblems (1) and (2) recursively.

            int leftSum = MaxSubSum3(arr, left, center);

            int rightSum = MaxSubSum3(arr, center+1, right); 

 // Solve the subproblem (3)

            int s1 = 0, lefts = 0;

            for (int i = center; i >= left; --i)

            {

                lefts += arr[i];

                if (lefts > s1)

                    s1 = lefts;

            }

            int s2 = 0, rights = 0;

            for (int i = center + 1; i <= right; ++i)

            {

                rights += arr[i];

                if (rights > s2)

                    s2 = rights;

            }

            // Combine the solutions of the subproblems.

            sum = s1 + s2;

            if (sum < leftSum)

                sum = leftSum;

            if (sum < rightSum)

                sum = rightSum;

        }

        return sum;

}

3. 动态规划法:

int MaxSubSum4(int* arr, int n, int& beg, int& end)

{

        int sum = 0, thisSum = 0, j = 0;

for (int i = 0; i < n; ++i)

        {

            // 根据动态规划式决定取舍。

            if (thisSum >= 0)

                thisSum += arr[i];

            else

            {

                this
Sum = arr[i];

                j = i;

            }

            if (thisSum > sum)

            {

                sum = thisSum;

                end = i;

                beg = j;

            }

        }

        return sum;

}

抱歉!评论已关闭.