最大M子段和

二维dp数组java

dp[i][j]前j个数字选取i段的最大和,必定要第j个数字数组

dp[i][j]=dp[i][j-1]+a[j-1] 这是指把第j个数字并入前面那些数字的最后一段优化

dp[i][j]=Max(dp[i][j],dp[i-1][m]+a[j-1]) 这是把第j个数字单独做为一段spa

时间复杂度(O(k*n^2))code

public int max_M_sum(int[] a,int k) {
        int[][] dp=new int[k+1][a.length+1];//dp[i][j]前j个数字选取i段的最大和,必定包含第j个数字
        dp[1][1]=a[0];
        for(int i=2;i<k+1;i++) dp[i][i]=dp[i-1][i-1]+a[i-1];
        
        for(int i=1;i<k+1;i++) {
            for(int j=i+1;j<a.length+1;j++) {
                dp[i][j]=dp[i][j-1]+a[j-1];//至关于把第j个数链接到前面的最后一段后面
                for(int temp=i-1;temp<j;temp++) {
                      dp[i][j]=Math.max(dp[i][j],dp[i-1][temp]+a[j-1]);
                }    
            }
        }
        return dp[k][a.length];//这里返回的不是最优解
    }

观察最上面的图发现,dp[i][j]只由左边的一位和上面的一段决定,并且是由上面一段的最大值决定的,所以能够进行优化blog

时间复杂度O(k*n)get

public int max_M_sum(int[] a,int k) {
        int[] pre=new int[a.length+1];//pre[i]少一段的最大值,从1到i之间的最大值
        int[] dp=new int[a.length+1];
        int tmp=-999999;
        for(int i=1;i<k+1;i++) {
           tmp=-999999;//不断刷新最左边的那个空的
           for(int j=i;j<a.length+1;j++) {
               dp[j] = Math.max(dp[j-1], pre[j-1])+a[j-1];
               pre[j-1]=tmp;
               tmp=Math.max(tmp, dp[j]);
           }            
        }    
        return tmp;
    }

https://www.nowcoder.com/practice/824af5cb05794606b56657bb3fa91f49?tpId=98&tqId=32843&tPage=1&rp=1&ru=/ta/2019test&qru=/ta/2019test/question-rankingio

这个笔试题,最终的段数能够小于k,求最大的就行,所以须要合并一下,减少复杂度,但仍是过不去,我也不知道为何class

import java.util.*;
public class Main{
    public static void main(String[] args) {
          Scanner sc=new Scanner(System.in);
          int n=sc.nextInt();
          int k=sc.nextInt();
          int[] a=new int[n];
          for(int i=0;i<n;i++) {
              a[i]=sc.nextInt();
          }
          int t=0;
          
          int[] b=new int[n];
          b[0]=a[0];
           for(int i=1;i<n;i++) {
              if(a[i]*a[i-1]>0) {//同号
                  b[t]+=a[i];
              }
              else
              {
                  t++;
                  b[t]=a[i];
              }
          }
          Main m=new Main();
          System.out.println(m.max_M_sum(b,k,t+1));
    }
    public int max_M_sum(int[] a,int k,int t) {
        if(t<=k) {
            int res=0;
            for(int i=0;i<t;i++) {
                if(a[i]>0) res+=a[i];
            }
            return res;
        }
        else{
            int[] pre=new int[t+1];//少一段的最大值,不必定包含最后一个
        int[] dp=new int[t+1];
        int tmp=-999999;
        int res=Integer.MIN_VALUE;
        for(int i=1;i<k+1;i++) {
           tmp=Integer.MIN_VALUE;//不断刷新最左边的那个空的
           for(int j=i;j<t+1;j++) {
               dp[j] = Math.max(dp[j-1], pre[j-1])+a[j-1];
               pre[j-1]=tmp;
               tmp=Math.max(tmp, dp[j]);
           }
        }    
        for(int i=0;i<t+1;i++) res=Math.max(res, dp[i]);
        return res;
        }
        
    }
}
相关文章
相关标签/搜索