算法-最大子序和

2020-11-15  本文已影响0人  li_礼光

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

方式一:暴力解法

public class _53_最大子序和 {
    public static void main(String[] args) {
        int nums[] = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
        System.out.println(maxSubArray(nums));
    }

    //暴力法
    //暴力解法的思路,第一层for 就是设置起始位置,第二层for循环遍历数组寻找最大值
    public static int maxSubArray(int[] nums) {
        int max = 0;
        int temp = 0;
        int left = 0;
        int right = 0;
        for (int i = 0; i < nums.length; i++) {
            temp = 0;
            for (int j = i; j < nums.length; j++) {
                temp += nums[j];
                //如果当前的相加<max,那么久已经是具有最大和的连续子数组
                if (temp > max) {
                    max = temp;
                    left = i;
                    right = j;
                }
            }
        }
        System.out.println("具有最大和的连续子数组起始位置:left:" + left + " right :" + right);
        return max;
    }
}

输出:

具有最大和的连续子数组起始位置:left:3 right :6
6

复杂度分析

两个for循序 :




方式二:贪心解法

//贪心解法,如何省掉一层for循环呢
//贪心贪的是哪里呢?
//如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方!
//同样的道理,遍历nums,从头开始用count累积,这里需要理清楚题意,具有最大和的连续子数组,返回其最大和。
//只要从头开始用count累积,用一个result记录当前累计最大的数, 只要count的累积不为负数。
//因为如果累计到为负数,就假定为-1,那么下一个i+1的元素相加 -1, 肯定得到的要i+1的元素小,所以还不如直接从i+1的元素开始
//那么就是可以理解为result是最大的和。

public static int maxSubArray2(int[] nums) {
  int result = 0;
  int count = 0;
  for (int i = 0; i < nums.length; i++) {
    count += nums[i];
    if (count > result) { 
      result = count;
    }
    if (count <= 0) 
      count = 0; 
    }
    return result;
}

复杂度分析

一个for循序 :




方式三:动态规划解法

public static int maxSubArray3(int[] nums) {
  //类似寻找最大最小值的题目,初始值一定要定义成理论上的最小最大值
  int result = Integer.MIN_VALUE;
  int numsSize = nums.length;
  int dp[] = new int[numsSize];//dp[i]表示nums中以nums[i]结尾的最大子序和
  //如果数组只有一个元素
  if (numsSize == 1) {
    return nums[0];
  }
  dp[0] = nums[0];
  result = dp[0];
  for (int i = 1; i < numsSize; i++) {
  // 跟贪心算法一样,如果因为如果累计到为负数,就假定为-1,那么下一个i+1的元素相加 -1, 肯定得到的要i+1的元素小,所以还不如直接从i+1的元素开始
    if (dp[i - 1] + nums[i] > nums[i]) {
      dp[i] = dp[i - 1] + nums[i];
    } else {
      dp[i] = nums[i];
    }
    if (result <= dp[i]) {
      result = dp[i];
    }
    System.out.println(" i = " + i + "  dp " + dp[i] + "    " + nums[i]);
  }
  return result;
}

一个for循序 :

上一篇下一篇

猜你喜欢

热点阅读