算法题目打卡:Ques20201025

最大子段和问题

给定整数序列,求该序列形如k=ijak的子段和的最大值,1)已知一个简单算法如下:

试分析该算法的时间复杂性。

答:时间复杂度为O(n^2)

2)试用分治算法解最大子段和问题,并分析算法的时间复杂性。

算法思路

需要在序列 中找到一段最优序列,将序列分为,与最邻近点对问题类似,最优序列所在的位置有以下3种情况:

分治法代码

#include<iostream>
#include<cstdio>
#include<map>
#include<string>
#include<set>
#include<vector>
using namespace std;
using namespace std;
// Q1 最大子段和
class Ques20201025
{
public:   
    void test() { 
        vector<int> arr = {-2,11,-4,13,-5,-2};
        cout << maxSum(arr,1, arr.size()-1) << endl;
        int i, j;
    }
private:
    // 分治法
    int maxSum(vector<int> &arr, int left, int right) {
        int sum = 0;
        if (left==right) {
            sum = arr[left]>0?arr[left]:0;         
        }
        else
        {
            int mid = left + (right - left) / 2;
            // 最优序列在左边和右边时,递归处理
            int leftsum=maxSum(arr, left, mid);
            int rightsum = maxSum(arr, mid + 1, right);
            // 第3种情况的处理,最优序列跨过中心点mid
            int s1 = 0; int lefts = 0;// s1
            for (int i = mid; i >= left;i--) {
                lefts += arr[i];
                if (lefts>s1) {
                    s1 = lefts;
                }
            }
            int s2 = 0;// s1
            int rights = 0;
            for (int i = mid+1; i <= right; i++) {
                rights += arr[i];
                if (rights > s2) {
                    s2 = right;
                }
            }
            sum = s1 + s2;// 加在一起
            if (sum < leftsum)sum = leftsum;
            if (sum < rightsum)sum = rightsum;
        }
        return sum;
    }
};
int main() {
    Ques20201025 qus = Ques20201025();
    qus.test();
}

实现效果

 

时间复杂度

 

解得T(n)=O(nlogn)

3)试说明最大子段和问题具有最优子结构性质,并设计一个动态规划算法解最大子段和问题。分析算法的时间复杂度。

说明

动态规划代码 

// 动态规划法
    //设一个b数组,存的是i-j的a[i:j]子串的最大值,则总问题变为max b[j].当b[j-1]>0时,b[j]=b[j-1]+a[j]否则直接a[j]
    // b[j]=max{b[j-1]+a[j],a[j]}
    int DnMaxSum(vector<int>& arr) {
        int n = arr.size() - 1;
        int sum = 0,b=0;
        for (int i = 1; i <= n; i++) {
            if (b > 0) b += arr[i];
            else b = arr[i];
            if (b > sum) sum = b;
        }
        return sum;
    }

时间复杂度

只有一个for循环,因此算法的时间复杂度和空间复杂度都是O(n).

猜你喜欢

转载自blog.csdn.net/Toky_min/article/details/109279626