zoukankan      html  css  js  c++  java
  • 关于求最大子段和的几种算法

    一、比较朴素的算法

    算法思想:我们确定每个子段和开始的位置,分别为第一个,第二个,第三个......第N个,然后计算从这个位置开始到这个位置之后的每个位置的子段和,更新记录最大的子段和。

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

    算法实现(Java):

    package com.Third;
    
    import java.util.*;
    public class Main3{
        public static int maxSum2(int a[]){
            int nowSum=0;//用于记录从指定位置到当前位置累加的值
            int maxSum=0;//用于记录当前最大的子段和
            for(int i=0;i<a.length;i++){
                nowSum=0;
                for(int j=i;j<a.length;j++){
                    nowSum=nowSum+a[j];
                    if(nowSum>maxSum){//更新最大子段和
                        maxSum=nowSum;
                    }
                }
            }
            
            return maxSum;
        }
        public static void main(String[] args) {
            int a[]={4,-3,5,-2,-1,2,6,-2};
            System.out.println(maxSum2(a));
        }
    }

    二、分治法(递归)

    算法思想:

    通过分治的思想求最大子段和,将数组分平均分为两个部分,则最大子段和会存在于三种情况下:
    1.最大子段和出现在左端
    2.最大子段和出现在右端
    3.最大子段和横跨在左右段  通过比较大小得到最大子段和

    时间复杂度:O(nlogn)

    算法实现(Java):

    package com.Third;
    /*
     * 通过分治的思想求最大子段和,将数组分平均分为两个部分,则最大子段和会存在于三种情况下:
     * 1.最大子段和出现在左端
     * 2.最大子段和出现在右端
     * 3.最大子段和横跨在左右段
     */
    public class Main {
        public static int maxSumRec(int []a,int start,int end){
            if(start==end){//这里是递归的函数出口
                if(a[start]>0){
                    return a[start];
                }else{
                    return 0;
                }
            }
            int maxLeftSumRec=maxSumRec(a,start,(start+end)/2);//计算左半边的最大字段和
            int maxRightSumRec=maxSumRec(a,((start+end)/2)+1,end);//计算右半边最大子段和
            //计算最大子段和在中间的情况
            int leftMaxMark=0;
            int leftSum=0;        
            for(int i=(start+end)/2;i>=0;i--){
                leftSum=leftSum+a[i];
                if(leftSum>leftMaxMark){
                    leftMaxMark=leftSum;
                }
            }
            int rightMaxMark=0;
            int rightSum=0;
            for(int i=((start+end)/2)+1;i<=end;i++){
                rightSum=rightSum+a[i];
                if(rightSum>rightMaxMark){
                    rightMaxMark=rightSum;
                }
            }
            int maxMidSumRec=leftMaxMark+rightMaxMark;
            //比较三种情况那种情况是最大的子段和
            int maxSum=maxLeftSumRec;
            if(maxSum<maxRightSumRec){
                maxSum=maxRightSumRec;
            }
            if(maxMidSumRec>maxSum){
                maxSum=maxMidSumRec;
            }
            return maxSum;
        }
        public static void main(String[] args) {
            int a[]={4,-3,5,-2,-1,2,6,-2};
            System.out.println(maxSumRec(a,0,7));
        }   
    }

    三、动态规划算法

    算法思想:

    运用了动态规划的思想来解决最大子段和问题:
    通过遍历累加这个数组元素,定时的更新最大子段和,
    如果当前累加数为负数,直接舍弃,重置为0,然后接着遍历累加。

    时间复杂度:O(n)

    算法实现(Java):

    package com.Third;
    /*
     * 这是运用了动态规划的思想来解决最大子段和问题:
     * 通过遍历累加这个数组元素,定时的更新最大子段和,
     * 如果当前累加数为负数,直接舍弃,重置为0,然后接着遍历累加。
     */
    public class Main1{    
       public static int maxSubSum1(int []a){
           int maxSum=0; int nowSum=0;
           for(int i=0;i<a.length;i++){
               nowSum=nowSum+a[i];
               if(nowSum>maxSum){//更新最大子段和
                   maxSum=nowSum;
               }
               if(nowSum<0){//当当前累加和为负数时舍弃,重置为0
                   nowSum=0;
               }
           }   
           return maxSum;
       }
       public static void main(String[] args) {
           int a[]={4,-3,5,-2,-1,2,6,-2};
           System.out.println(maxSubSum1(a));
       }
    }
  • 相关阅读:
    Codeforces Beta Round #92 (Div. 2 Only) B. Permutations 模拟
    POJ 3281 Dining 最大流 Dinic算法
    POJ 2441 Arrange the BUlls 状压DP
    URAL 1152 Faise Mirrors 状压DP 简单题
    URAL 1039 Anniversary Party 树形DP 水题
    URAL 1018 Binary Apple Tree 树形DP 好题 经典
    pytorch中的forward前向传播机制
    .data()与.detach()的区别
    Argparse模块
    pytorch代码调试工具
  • 原文地址:https://www.cnblogs.com/xiaotiaosi/p/6832637.html
Copyright © 2011-2022 走看看