蓝桥杯算法基础(26)子数组最大累加和,子矩阵最大累加和

文章介绍了如何使用Java编程语言,通过递归和动态规划方法解决给定数组和矩阵的子数组最大累加和问题,包括基本的暴力遍历和优化的动态规划解决方案。
摘要由CSDN通过智能技术生成

子数组最大累加和

给定一个数组arr,返回子数组的最大累加和
例:arr=[1,-2,3,5,-2,6,-1];所有的子数组中[3,5,-2,6]可以累加出最大的和12,所以返回12

static void findByForce(int[] arr){

    int manSum=arr[0];
    for(int i=0;i<arr.length;i++){
    int sum=arr[j];//某个元素为子数组的第一个元素
    int maxOfJ=sum;

    for(int i=j;i<arr.length;i++){
    sum+=arr[i];//累加后续元素
        if(sum>maxOfJ){
        maxOfJ=sum;//某个元素后续最大累加
        }
    }

    if(maxOfJ>maxSum){
    maxSum=maxOfJ;// 总的最大值
    }

    }

    System.out.println(maxSum);
}


//递推法 o(n)
static int findByDp(int[] arr){
  int sumJ=arr[0];///前J个元素的最大贡献
  int max=sumJ;

  int left=0;right=0;//***若是求最大值之间的下标
  int temp;//记录最大值的letf
  for(int j=1;j<arr.length;j++){
   if(sumJ>=0){//左子表的最大和为正,继续向后累加
   sumJ+=arr[j];//若是大于0,则可以要前面的一段
   }else{//若是小于0,则从当前位置重新开始
   sumJ=arr[j];
  // left=j;//重新开始时,更新left
   //**上面那行是错的,他最终只会停在最后一次sumJ小于0的位置
   temp=j;
   }

   if(sumJ>max){//最大值
   left=temp;//*如此,只有最大值得到更新,才能更新letf
   max=sumJ;
  // 每次求得最大值,更新最大值时,同时更新right
   right=j;
   }
  }
  return max;

}

子矩阵最大累加和

给定一个矩阵matrix,其中的值有正、有负、有0、返回子矩阵的最大累加和
例如,matrix为:
-1 -1 -1
-1  2  2
-1 -1 -1
其中最大累加和的子矩阵为
2 2
所以返回4



 从第一行开始,作为起始行,先求第一行,找最大子数组和,再将下一行于上一行累加到一起,找最大子数组和
 然后变更起始行,继续之前的循环







 private static int maxSum(int[][] matrix){

    int beginRow=0;
    final int M=matrix.length;
    final int N=matrix[0].length;

    int[] sums=new int[N];//按列求和

    int max=0;//历史最大的子矩阵和

    while(beginRow<M){//起始行
        for(int i=beginRow;i<M;i++){//从起始行到最后一行
            //按列累加
            for(int j=0;j<N;j++){
            sums[j]+=matrix[i][j];
            }
            //累加完成
            int t=findByDp(sums);//求出sums的最大和子数组
            if(t>max)
            max=t;

        }
        //另起一行作为起始行,把sums清零
    Arrays.fill(sums,0);//将sums的每个元素都设定为0
    beginRoww++;//以下一行作为起始行
    }
    return max;

}

public static int findByDp(int[] arr){
    if(arr.length==0)return 0;
  int sumJ=arr[0];///前J个元素的最大贡献
  int max=sumJ;

  int left=0;right=0;//***若是求最大值之间的下标
  int temp;//记录最大值的letf
  for(int j=1;j<arr.length;j++){
   if(sumJ>=0){//左子表的最大和为正,继续向后累加
   sumJ+=arr[j];//若是大于0,则可以要前面的一段
   }else{//若是小于0,则从当前位置重新开始
   sumJ=arr[j];
  // left=j;//重新开始时,更新left
   //**上面那行是错的,他最终只会停在最后一次sumJ小于0的位置
   temp=j;
   }

   if(sumJ>max){//最大值
   left=temp;//*如此,只有最大值得到更新,才能更新letf
   max=sumJ;
  // 每次求得最大值,更新最大值时,同时更新right
   right=j;
   }
  }
  return max;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值