LeetCode简单篇----5----求最大子序和

LeetCode官方题解:https://leetcode-cn.com/problems/maximum-subarray/solution/zui-da-zi-xu-he-by-leetcode/

目录

一、需求

二、分治算法

思路分析

代码实现

复杂度分析

三、贪心算法

思路分析

代码实现

代码优化版

复杂度分析

四、动态规划算法

思路分析

代码实现

复杂度分析

五、暴力匹配法

思路分析

代码实现

复杂度分析


一、需求

        A:给定一个整数数组nums,找到一个具有最大和的连续子数组(最少包含一个元素);

        B:返回子数组的最大和;

二、分治算法

  • 思路分析

        A:定义方法,递归求最大子序列和,返回值类型为int,参数列表为数组名,起始索引和结束索引;

        B:递归结束条件是当只有一个元素的时候,直接返回该元素;

        C:定义中间值mid=left+(right-mid)/2,先求左子数组最大值,然后求右子数组最大值;

        D:求出横跨序列前半部分的最大和,以及横跨序列后半部分的最大和,并将此二者相加;

        E:最后对C和D中共三个最大值进行比较,返回最大的那个;

  • 代码实现

public int maxValue(int[] nums,int left,int right) {
        //定义左右子数组最大值
        int maxLeftSum=0, maxRightSum=0;
        //定义横跨序列左右两边最大值
        int maxLeftBorderSum=Integer.MIN_VALUE, maxRightBorderSum=Integer.MIN_VALUE;
        //定义用于求解横跨序列两边最大值的辅助变量
        int leftBorderSum=0, rightBorderSum=0;
        //定义中间值
        int mid = left + (right - left) / 2;
        
        //只剩一个元素
        if(left == right) {
            return nums[left];
        }

        //求左右子数组最大值
        maxLeftSum = maxValue(nums,left,mid);//-2
        maxRightSum = maxValue(nums,mid+1,right);//-1

        //横跨序列前半部分和
        for(int i = mid; i >= left; i--) {
            leftBorderSum += nums[i];
            if(leftBorderSum > maxLeftBorderSum) {
                maxLeftBorderSum = leftBorderSum;
            }
        }
        //横跨序列的后半部分和
        for(int i = mid + 1; i <= right; i++){
            rightBorderSum += nums[i];
            if(rightBorderSum > maxRightBorderSum) {
                maxRightBorderSum = rightBorderSum;
            }
        }

        int BorderSum = maxLeftBorderSum + maxRightBorderSum;

        //求三个数中的最大值
        if( maxLeftSum > maxRightSum)
            return maxLeftSum > BorderSum ? maxLeftSum : BorderSum;
        else
            return maxRightSum > BorderSum ? maxRightSum : BorderSum;

    }
    
    public int maxSubArray(int[] nums) {
        return maxValue(nums,0,nums.length-1);
    }
  • 复杂度分析

        A:时间复杂度O(NlogN);

        B:空间复杂度O(logN),递归时栈使用的空间;

三、贪心算法

  • 思路分析

  • 代码实现

public int maxSubArray(int[] nums) {
        //定义result和sum
        int result = Integer.MIN_VALUE;
        int sum = 0;
       //遍历数组
       for(int i = 0; i < nums.length; i++) {
           //更新sum值
           sum += nums[i];
          //记录result
          result = Math.max(sum,result);
          //更新sum
          if(sum < 0) {
              sum = 0;
          }
       }
       return result;
    }
  • 代码优化版

public int maxSubArray(int[] nums) {
    int n = nums.length;
    int currSum = nums[0], maxSum = nums[0];

    for(int i = 1; i < n; ++i) {
      //当前位置的最大和
      currSum = Math.max(nums[i], currSum + nums[i]);
      //迄今为止的最大和
      maxSum = Math.max(maxSum, currSum);
    }
    return maxSum;
  }
  • 复杂度分析

        A:时间复杂度O(N);

        B:空间复杂度O(1),只使用了常数空间;

四、动态规划算法

  • 思路分析

 

  • 代码实现

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int maxSum = nums[0];

        for(int i = 1; i < n; i++) {
            if(nums[i-1] > 0) {
                nums[i] += nums[i-1];
            }
            maxSum = Math.max(nums[i],maxSum);
        }
    return maxSum;
    }
}
  • 复杂度分析

        A:时间复杂度O(N);

        B:空间复杂度O(1),只使用了常数空间;

五、暴力匹配法

  • 思路分析

        A:求数组所有的子数组的和进行比较,需要两层循环;

        B:外循环记录每次开始比较的起始位置;

        C:内循环遍历从起始位置开始到最后的所有元素;

  • 代码实现

public int maxSubArray(int[] nums) {
        int n = nums.length;
        int maxSum = Integer.MIN_VALUE;

        for(int i = 0; i < n; i++) {
            int sum = 0;
            for(int j = i; j < n; j++) {
                sum += nums[j];
                maxSum = Math.max(maxSum,sum);
            }
        }
        return maxSum;
    }
  • 复杂度分析

        A:时间复杂度O(N^2);

        B:空间复杂度O(1);

发布了63 篇原创文章 · 获赞 9 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Sruggle/article/details/103996065