• Maximum Subarray


    问题描述

    给定一个序列(A_0)(A_1)(A_2)、...、(A_{n-1}),求(A_i+A_{i+1}+...+A_j)的最大值。

    解一

    暴力枚举左端点(i)和右端点(j),之后计算(A_i)(A_j)之间的和,时间复杂度(O(n^3)),很容易TLE。

    #define INF 0x7FFFFFFF
    
    int sub_sum(int a[],int n)
    {
    	int MAX = -INF;
    	for(int i = 0;i < n;i++)
    	{
    		for (int j = i; j < n; j++)
     		 {
       			int temp = 0;
       			for (int k = i; k <= j; k++)
      			{
        				temp += a[k];
      			}
       			if (temp > MAX)
       			{
       				MAX = temp;
       			}
     		 }
    	}
    	return MAX;
    }
    

    解二

    输入数据时记录前缀和,预处理(sum[i] = A[0] + ... + A[i]),因此(A_i+A_{i+1}+...+A_j=sum[j]-sum[i-1]),复杂度优化为(O(n^2))

    int sub_sum(int a[],int n)
    {
    	int MAX = -INF;
    	for(int i = 0;i < n;i++)
    	{
    		for(int j = i;j < n;j++}
    		{
    			int temp = sum[j] - sum[i - 1];
    			if(temp > MAX)
    				MAX = temp;
    			else
    				temp = 0;
    		}
    	}
    	return MAX;
    }
    

    解三

    动态规划,复杂度(O(n))
    定义状态数组(dp[i]),表示以(A[i])结尾的连续序列的最大和,这样就只有两种情况:
    1,该连续序列只有(A[i])这一个元素;
    2,该序列有多个元素,从之前的(A[p])开始,到(A[i])结束。
    对于1,最大和就是(A[i])
    对于2,最大和是(dp[i - 1]+A[i]),因为(dp[i])要求以(A[i])结尾,所以即使(A[i])为负数,(dp[i])仍然等于(dp[i - 1]+A[i])
    所以状态转移方程就是:

    [dp[i]=max{{A[i],dp[i-1]+A[i]}} ]

    边界是(dp[0]=A[0])
    所以枚举(i),得到(dp)数组,求出(dp)数组最大值即可。

    可以看到,每次计算(dp[i])只用到(dp[i-1]),不直接用到之前的信息,这就是状态的无后效性,只有这样,动态规划才可能得到正确结果。

    int dp[5010];
    dp[0] = a[0];
    
    int sub_sum(int a[],int n)
    {
    	for(int i = 1;i < n;i++)
    	{
    		//状态转移方程
    		dp[i] = max(a[i],dp[i - 1] + a[i]);
    	}
    
    	int k = 0;
    	for(int i = 1;i < n;i++)
    	{
    		if(dp[i] > dp[k])
    			k = i;
    	}
    	return dp[k];
    }
    

    为了避免使用(dp[])数组,可以将空间复杂度优化为(O(1))

    class Solution {
    public:
        int maxSubArray(vector<int>& nums) {
            int allSum = INT_MIN, curSum = 0;
            
            int n = nums.size();
            for(int i = 0;i < n;i++)
            {
                curSum = max(nums[i], curSum + nums[i]);
                if(curSum > allSum)
                {
                    allSum = curSum;
                }
            }
            
            return allSum;
        }
    };
    
  • 相关阅读:
    SpringMVC中的适配器
    JVM的理解
    设计模式 特点比较
    AOP代理模式
    Spring配置补充
    MayBatis与Spring的整合
    增强和注解
    注入
    Mybatis的执行过程
    k8s认证与授权
  • 原文地址:https://www.cnblogs.com/EIMadrigal/p/12130801.html
Copyright © 2020-2023  润新知