最大子序列和四种解法(java)

本文介绍了如何用Java解决最大子序列和问题,包括暴力法、分治法、动态规划和贪心法。动态规划是通过状态转移方程找到最大子序列和,而贪心法则从头遍历数组,根据前一个子序列和来更新当前和。测试结果显示了各种方法的效率和效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最大子序列和

题目描述

题目:求给定数组中的最大连续子序列和

示例 :[1,3,-2,4 ,-5]

输出:6

解法一:暴力法(超时)

两层循环暴力求解

public int solution1(int[] nums){
        int ans = nums[0];
        for (int i = 0; i < nums.length; i++) {
            int sum = 0;
            for (int j = i; j <nums.length ; j++) {
                sum+=nums[j];
                if (sum>ans){
                    ans = sum;
                }
            }
        }
        return ans;
    }


解法二:分治法

思路:最大和子序列出现在一下三种情况:

  • 子序列出现在数组的左边
  • 子序列出现在数组的右边
  • 子序列出现在中间

根据这三种情况进行分治,每个子任务求出对应区间中左右两种情况的最大值返回与第三种情况进行比较

public int solution2(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        } else {
            return  digui(0 , nums.length-1 , nums);
        }
    }
    public int digui(int l, int r, int[] nums) {
        if(r<l){
            return Integer.MIN_VALUE;
        }
        int mid = (l + r) / 2;
        int left = digui(l, mid - 1, nums);
        int right = digui(mid + 1, r, nums);
        int leftSum = 0;
        int sum =0 ;
        for (int i = mid-1; i >l ; i--) {
            sum += nums[i];
            leftSum = Math.max(leftSum  ,sum);
        }
        int rightSum = 0;
        sum = 0;
        for (int i = mid+1; i <= r; i++) {
            sum += nums[i];
            rightSum = Math.max(rightSum , sum);
        }
        return Math.max((left+nums[mid]+right) , Math.max(left, right));
    }


解法三:动态规划

假设序列为 nums[len],那么在区间[0,i]内的最大子序列和区间[0,i-1]这个区间之内的子序列之间有什么关系?

设区间[0 , k]中的最大和子序列的值为G(k)

那么状态转移方程应该是G(k) = max(G(k) , G(k)+G(k-1))

public int solution3(int[] nums) {
        if(nums == null || nums.length ==0){
            return 0;
        }
        int ans = nums[0];
        for (int i = 1; i < nums.length; i++) {
            nums[i] = nums[i]>(nums[i-1]+nums[i])? nums[i]:(nums[i-1]+nums[i]);
            if(nums[i]>ans){
                ans = nums[i];
            }
        }
        return ans;
    }
   


解法四:贪心法

思路:从头开始遍历求和,假设遍历到G(k)时,假设G(k-1)小于0 ,不对G(k)做改动,假设G(k-1)大于0,则更新G(k)的值为G(k)+G(k-1)

上面的操作和动态规划类似,假设G(k-1)小于0,遍舍弃k前面的数,从k开始计数。

 public int solution4(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int pre = nums[0];
        for (int i = 1; i <nums.length ; i++) {
            if(pre>0){
                nums[i] = pre = pre+nums[i];
            }else {
                pre = nums[i];
            }
        }
        int max = Arrays.stream(nums).max().getAsInt();
        return max;
    }


测试结果

public static void main(String[] args) {
        System.out.println(new maxSubArray().solution1(new int[]{1,2,3}));
        System.out.println(new maxSubArray().solution2(new int[]{1,2,3}));
        System.out.println(new maxSubArray().solution3(new int[]{1,2,3}));
        System.out.println(new maxSubArray().solution4(new int[]{1,2,3}));
    }

output:
6
6
6
6


更多

更多内容请关注panrh.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值