【实际应用】java实现最大子列和问题

本文介绍了四种不同的算法来解决最大子列和问题,包括暴力法、动态规划、分治策略和在线处理。解法2通过避免重复加法将复杂度降低到O(n^2),解法3利用递归实现分而治之,解法4则实现了在线处理,每输入一个数据就更新最大子列和。这些算法在效率和内存使用上有所不同,适用于不同场景的需求。
摘要由CSDN通过智能技术生成

 

目录

解法1 暴力法(比较所有子列和,取最大值)O(n^3)

解法2:O(n^2) 不再做重复的加法

解法3: 分而治之

解法4 在线处理

解法1 暴力法(比较所有子列和,取最大值)O(n^3)

// 暴力求解,求出每个子列和,复杂度 三次方
    public static int MaxSum(int arr[]){
        // 求最大子列和, 先取子列并求和
        int maxSum = 0;
        for(int i = 0; i < arr.length; i++){  // i 为子列左侧位置
            for(int j = i; j < arr.length; j++ ){ // j为子列右侧位置
                int thisSum = 0;
                for(int k = i; k <= j;k++){ // k进行子列和计算
                    thisSum += arr[k];
                    if (maxSum < thisSum){
                        maxSum = thisSum;
                    }
                }
            }
        }
        return maxSum;
    }

解法2:O(n^2) 不再做重复的加法

// 解法2
    public static int MaxSum2(int arr[]){
        int maxSum = 0;
        for(int i = 0; i < arr.length; i++){ // i为子列左侧位置
            int thisSum = 0;   // arr[i] 到 arr[j]的子列和
            for(int j = i ; j < arr.length; j++){
                thisSum += arr[j];
                if(thisSum > maxSum){
                    maxSum = thisSum;
                }
            }
        }
        return maxSum;
    }
}

 解法3: 分而治之

利用递归求解,设置递归结束条件后,分别求出左侧子列和右侧子列的最大子列和,再求跨越边界的最大子列和,返回三个数中的最大值

// 分而治之,递归解决左右两侧的最大连续子列和
    //返回最大子列和
    public static int MaxSum3(int arr[]){
        int maxSum;
        maxSum = DivideandCounter(arr,0,arr.length -1);
        return maxSum;
    }

    // 返回三个数中的最大值
    public static int Max3(int a, int b, int c){
        int max = 0;
        if(a > max){
            max = a;
        }
        if (b > max){
            max = b;
        }
        if(c > max){
            max = c;
        }
        return max;
    }

    public static int DivideandCounter(int arr[], int left, int right){
        int maxLeftSum, maxRightSum; //存放左右两个子列的结果

        // 递归终止条件,子列只有一个数字,正数返回数值,负数返回0
        if(left == right){
            if(arr[left] > 0){
                return arr[left];
            }else{
                return 0;
            }
        }

        // 先将数组分成两个部分
        int center = (left + right) / 2;  // 找到中分点
        // 递归调用解决左侧子列和右侧子列问题
        maxLeftSum = DivideandCounter(arr, left, center);
        maxRightSum = DivideandCounter(arr, center + 1 , right);

        // 解决跨越边界的问题
        int rightBorderSum, maxRightBorderSum;
        // 从中心向右方扫描
        maxRightBorderSum = 0;
        rightBorderSum = 0;
        for(int i = center + 1 ; i <= right; i++){
            rightBorderSum += arr[i] ;
            if(maxRightBorderSum < rightBorderSum){
                maxRightBorderSum = rightBorderSum;
            }
        }

        // 从中心往左侧扫描
        int leftBorderSum, maxLeftBorderSum;
        maxLeftBorderSum = 0;
        leftBorderSum = 0;
        for(int i = center ; i >= left; i --){
            leftBorderSum += arr[i] ;
            if(maxLeftBorderSum < leftBorderSum){
                maxLeftBorderSum = leftBorderSum;
            }
        }

        return Max3(maxLeftSum, maxRightSum, (maxLeftBorderSum + maxRightBorderSum)) ;

    }

解法4 在线处理

“在线”的意思是指每输入一个数据就进行即时处理,在任何一个地方中止输入,算法都能正确给出当前的解。

算法效率高是有代价的:其正确性不明显(他人难以理解算法是如何工作的)

public static int MaxSum4(int arr[]){
        int thisSum = 0;
        int maxSum = 0;
        for(int i = 0; i < arr.length ; i++){
            thisSum += arr[i]; // 每输入一个数都进行一次处理
            if(thisSum > maxSum){
                maxSum = thisSum;
            }else if(thisSum < 0){ // 如果当前子列为负,则不可能使后面子列和增大,归零
                thisSum = 0;
            }
        }
        return maxSum;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值