LeetCode(053)-Maximum Subarray

版权声明:中华人民共和国持有版权 https://blog.csdn.net/Fly_Fly_Zhang/article/details/89857191

题目:

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

翻译:

给定整数数组号,找到具有最大和的相邻子数组(至少包含一个数字)并返回其和。
例子:
输入:(2,1,3、4、1、2、1、5、4],
输出:6
说明:[4,-1,2,1]的和最大= 6。
跟进:
如果您已经找到了O(n)的解决方案,那么尝试使用分治方法编写另一个解决方案,这种方法更加微妙。

动态规划:O(n)

思想:

定义两个变量,一个记录历史最大连续和(max),一个记录当前最大和(maxsum)。
遍历当前数组,比较当前元素+maxsum是否大于maxsum,是的话旧更新当前最大和。
在将当前最大和历史最大和进行比较。将最大的赋值给max。

class Solution {
    public int maxSubArray(int[] nums) {
            
        int max = nums[0];
        int maxsum = nums[0];
        for(int i = 1; i < nums.length; i++){            
            maxsum = maxsum + nums[i] > nums[i] ? maxsum + nums[i] : nums[i];
            max = maxsum > max ? maxsum : max;
        }
        return max;
    
    }
}

分治算法:

分治策略:将数组分成两部分,那么最大子数组会可能在以下三个部分。
  • 左侧数组的最大子数组
  • 右侧数组的最大子数组
  • 左侧数组以右侧边界为边界的最大子数组+右侧数组以左侧边界为边界的最大子数组
class Solution {
    public int maxSubArray(int[] nums) {
        if(nums==null || nums.length==0)       
            return 0;
        return subArray(nums,0,nums.length-1);
    
    }
    //进行三种操作,1,左边递归,2,右边递归,3 从mid位置开始往两边扩散找最大连续子数组的和。
    private int subArray(int[] nums,int l,int r){
        //退出递归条件
        if(l==r)
            return nums[l];
        int mid=(l+r)>>1;
        //将三种操作的结果进行比较,找出最大值。
        return max(subArray(nums,l,mid),subArray(nums,mid+1,r),maxCross(nums,l,mid ,r));
    }
    
    //将从mid位置将数组分为两部分进行遍历,注意,只能从mid位置向两边遍历
    //因为这个函数想要找的是mid角标在的连续子数组的最大值。
    private int maxCross(int[] nums,int l ,int mid ,int r){
        int maxL=nums[mid];  //这两个不能置0,因为有的元素小于0
        int maxR=nums[mid+1];
        int na=maxL;
        //遍历左边,找到从mid位置连续的最大和
        for(int i=mid-1 ; i>=l ;i--){
            na+=nums[i];
            if(na>maxL)
                maxL=na;
        }
        int nb=maxR;
        //遍历右边
        for(int j= mid+1+1 ; j<=r ; j++){
            nb+=nums[j];
            if(nb>maxR)
                maxR=nb;
        }
        return maxL+maxR;
    }
    //得到三个元素的最大值
    private int max(int a,int b,int c){
        return Math.max(a,Math.max(b,c));
    }
}

猜你喜欢

转载自blog.csdn.net/Fly_Fly_Zhang/article/details/89857191
今日推荐