leetcode.53 最大子序和

思路一:暴力破解

外循环控制子序列的头,内循环控制子序列的尾

class Solution {
    public int maxSubArray(int[] nums) {
        int max=Integer.MIN_VALUE;
        for(int i=0;i<nums.length;i++)
        {
            int sum=0;
            for(int j=i;j<nums.length;j++)
            {
                sum += nums[j];
                if(sum>max)
                max=sum;
            }
        }
        return max;
    }
}

//下面这种调用了Math的max方法作为比较,上面用的是三元表示法
class Solution {
    public int maxSubArray(int[] nums) {
        if(nums.length==1)
        return nums[0];
        int max=Integer.MIN_VALUE;
        for(int i=0;i<nums.length;i++)
        {
            int total=0;
            for(int j=i;j<nums.length;j++)
            {
                total+=nums[j];
                max=Math.max(total,max);
            }
        }
        return max;

        
    }
}

时间复杂度O(n^2)

空间复杂度O(1)

思路二  分治法(递归)

分治法的主要思想是:

1、将大问题分解成小问题,将所有的小问题解决,那么大问题即解决

2、子问题的求解思路和大问题思路相同

3、存在终止条件

和常规的分治不同,常规是不断的一分为二,这是一分为三

下面的图解可以结合代码理解,最好是先把https://mp.csdn.net/mp_blog/creation/editor/118756766中的分治解法捋捋清楚,好家伙这两道题看了两天

 重点是理解“跨越中间”的子序列

解释上图:向左边找最大子序列-2=(-3+1)

代码实现如下:

class Solution {
    public int maxSubArray(int[] nums) {
        return getMax(nums,0,nums.length-1);
    }
//寻找最大子序列的和的函数
    public int getMax(int[] arrs,int left,int right)
    {
        if(left==right)
        return arrs[left];
        int mid=left+(right-left)/2;
        int leftMax=getMax(arrs,left,mid);//左递归
        int rightMax=getMax(arrs,mid+1,right);//右递归
        int crossMax=crossMax(arrs,left,right);//中间最大子序列
        return Math.max(leftMax,Math.max(crossMax,rightMax));//左右中作比较然后返回
        
    }
//中间最大子序列的和
    public int crossMax(int[] arrs,int left,int right)
    {
        int mid=left+(right-left)/2;
        int leftSum=arrs[mid];
        int leftMax=leftSum;
//找中间的左边最大子序列的和
        for(int i=mid-1;i>=left;i--)
        {
            leftSum += arrs[i];
            leftMax=leftSum>leftMax?leftSum:leftMax;
        }
        int rightSum=arrs[mid+1];
        int rightMax=rightSum;
//找中间的右边最大子序列的和
        for(int i=mid+2;i<=right;i++)
        {
            rightSum += arrs[i];
            rightMax=rightSum>rightMax?rightSum:rightMax;
        }
//中间子序列分为“中间往左”的最大子序列和“中间往右”的最大子序列,左右的和即为中间最大子序列
        return leftMax+rightMax;
    }
}

【自己看的总结:一定不要被绕进去,分析终止条件以及只分析这一层与下一层两层的关系,当左边的递归到底第一次返回,右边的递归开始,接着又到右边的左递归,整个过程left、right、mid是一直改变的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_40396568

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值