53.最大子数组和

4 阅读1分钟

53.最大子数组和

方法一:Kadane's Algorithm(卡登算法 / 最大子数组和算法)

动态规划DP + 贪心

贪心:眼前好就留,不好就扔,只看眼前 1 步

动态规划:用前面算过的结果,推现在的结果,看前面所有步

比较:贪心看眼前,DP 看全局。

核心思想:如果前面的和是负数,就直接扔掉,从当前数重新开始。负数只会拖累后面的数,不可能让总和变大。

class Solution {
    public int maxSubArray(int[] nums) {
        int current = 0;
        int max=nums[0];
​
        for(int num: nums){
            if(current<0) current=0;
            current+=num;
            if(current > max) max=current;//这一句等价于max = Math.max(max, current);
        }
        return max;
    }
}
​
//只遍历数组 1 次
//时间复杂度:O(n)

方法二:暴力枚举(超时了无法ac)

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int max = nums[0]; // 先存第一个数当最大值
​
        // 枚举所有起点 i
        for (int i = 0; i < n; i++) {
            // 枚举所有终点 j(j >= i)
            for (int j = i; j < n; j++) {
                // 计算从 i 到 j 的和
                int sum = 0;
                for (int k = i; k <= j; k++) {
                    sum += nums[k];
                }
                // 如果更大,就更新 max
                if (sum > max) {
                    max = sum;
                }
            }
        }
        return max;
    }
}
​
//三层循环,时间复杂度 O(n³)
//数组长度 100 就要跑 100×100×100 = 100 万次
//题目给 n=1e5,暴力会直接超时,跑不出来
知识点
Java Math 类常用方法(直接用,不用导包)
  1. 取最大、最小

    Math.max(a, b) → 取大的 Math.min(a, b) → 取小的

    Math.max(3, 5);   // 5
    Math.min(3, 5);   // 3
    
  2. 绝对值

    Math.abs(x)

    Math.abs(-5);     // 5
    Math.abs(-99);    // 99
    
  3. 平方根

    Math.sqrt(x)

    Math.sqrt(16);    // 4.0
    
  4. 次方

    Math.pow(a, b) a 的 b 次方

    Math.pow(2, 3);   // 8.0
    
  5. 随机数

    Math.random() 返回 0.0 ~ 1.0 之间的随机小数

    (int)(Math.random() * n);//生成 0 ~ n-1 的随机整数: