最大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;
        }
        
    }
}
相關文章
相關標籤/搜索