LeetCode高频题53. 最大子数组和

LeetCode高频题53. 最大子数组和

提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题
在这里插入图片描述


文章目录

  • LeetCode高频题53. 最大子数组和
    • @[TOC](文章目录)
  • 题目
  • 一、审题
  • 子数组:考虑以i开头或者i结尾的子数组的答案
  • 还有一种写法:考虑以位置开头的子数组累加和最大值是多少?用cur持续收集,发现cur<0,从新开头
  • 总结

题目

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。


一、审题

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:

输入:nums = [1]
输出:1
示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


子数组:考虑以i开头或者i结尾的子数组的答案

必须以0结尾的情况下,subSum是多少?
必须以2结尾的情况下,subSum是多少?
必须以2结尾的情况下,subSum是多少?
……
必须以i结尾的情况下,subSum是多少?
……
必须以N-1结尾的情况下,subSum是多少?
中途subSum最大值更新给max

复杂度o(n)一遍搞定

dp[i]就是以i结尾的子数组的最大累加和!

(1)dp[i]=max可能只包含i那个数,前面不能包含
LeetCode高频题53. 最大子数组和_第1张图片
(2)可能包含前面的最大值:dp[i-1]+[i]
比如1- 2 5
5+2=7=max
LeetCode高频题53. 最大子数组和_第2张图片

因此,我们只需要中途填一个dp表
当然,dp[0]=[0],0位置就是[0]自己,没得选
任意位置dp[i]取值是(1)(2)之最大值max

这就是典型的从左往右的尝试模型(DP)
手撕代码实在是太容易不过了!

        //子数组:考虑以i开头或者i结尾的子数组的答案
        public static int maxSubArraySum(int[] arr){
            if (arr == null || arr.length == 0) return 0;
            if (arr.length == 1) return arr[0];

            int N = arr.length;
            int max = Integer.MIN_VALUE;//系统最小

            int[] dp = new int[N];//dp[i],必须以i结尾的子数组的最大累加和
            dp[0] = arr[0];//首位置就一个0位置
            max = Math.max(max, dp[0]);//中途o(n)更新max
            for (int i = 1; i < N; i++) {
                dp[i] = Math.max(arr[i], arr[i] + dp[i - 1]);//要么前面太小,只有i,要么前面足够大,累加过来
                max = Math.max(max, dp[i]);
            }

            return max;
        }

测试一把:

    public static void test(){
        int[] arr = {-2,1,-3,4,-1,2,1,-5,4};
        int[] arr2 = {-2,1,-3,4,-1,2,1,-5,4};
        Solution solution = new Solution();
        System.out.println(solution.maxSubArray(arr));
        System.out.println(solution.maxSubArraySum(arr2));
    }

    public static void main(String[] args) {
        test();
    }

结果:

6
6

LeetCode测试:
LeetCode高频题53. 最大子数组和_第3张图片
这个咋还挺慢的
可能就是计算dp填表这事有点慢

下面不要填表,直接一个参数cur搞定,可能速度就很快的。


还有一种写法:考虑以位置开头的子数组累加和最大值是多少?用cur持续收集,发现cur<0,从新开头

这不是arr有正负零吗??
咋着才能最大呢?????

不妨设从左往右累加和为cur

反正我们期待cur最好越过0,变大,这样max更新更大,否则
一旦cur<0的话,我们将cur清零来过,这样保证即使加负数,也不要更大的数,不要太小

这么做,就是考虑以i位置开头的子数组累加和最大值是多少?
用cur持续收集,发现cur<0,从新开头,保证子数组累加和最大

手撕代码问题不大:

        //考虑以i位置开头的子数组累加和最大值是多少?
        public static int maxSubArraySumHead(int[] arr){
            if (arr == null || arr.length == 0) return 0;
            if (arr.length == 1) return arr[0];

            int N = arr.length;
            int max = Integer.MIN_VALUE;//系统最小
            int cur = 0;//以0位置开头的累加和,准备收集,中途cur<0就要清零重新开头
            for (int i = 0; i < N; i++) {
                cur += arr[i];
                max = Math.max(max, cur);
                cur = cur < 0 ? 0 : cur;
            }
            return max;
        }

测试:

System.out.println(solution.maxSubArraySumHead(arr2));
6

很OK的
LeetCode测试:
LeetCode高频题53. 最大子数组和_第4张图片


总结

提示:重要经验:

1)遇到子数组,显然考虑以i结尾的情况,或者考虑以i开头的情况,收集答案,然后整结果就行
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

你可能感兴趣的:(大厂面试高频题之数据结构与算法,leetcode,子数组累加和,最大子数组累加和,连续子数组,累加和)