算法简单题,吾辈重拳出击 - 连续子数组的最大和

简介: 对算法感到畏惧的 xdm,咱不求一口吃个胖子,先对算法简单题重拳出击,尝试建立自信,训练基础算法思维,不日定能大杀四方、所向披靡。

image.png

一小段废话:其实在更文活动下面很少看到有 6 级作者会选择坚持更文了。可能更文活动的主要面向对象是初中级写作的掘友。但自问一句,6 级作者就是写作高手了吗?未必吧。 有 3 点思考:1. 掘金是一个在成长的技术平台,以前的流量分配也未必精准,有些文章可能发展期意外被推流了,也并不能说明什么。很多作者也是,曾经辉煌过,但后续因为某些原因,也逐渐也在创作视野中消失了。写作很难是一锤定音、一招即中,也不是标准意义上的被动收入,唯有持续才有长久。2. 真的能保证在放弃持续更文的情况下,创作好文吗?不知道别人如何,本瓜更多的是在持续更的过程中才会迸发一些好文的灵感或创作出好文。如果空想、干想好文,结果就是被拖延搁置了。3. 能薅一下羊毛也挺不错的吧?虽然有些东西也没啥用,但是每次拿到证书、更文激励,还是会开心满足。认真做过的都知道是不简单的,所以就做吧,以一颗初心,学徒之心,苟日新、日日新!!


对于前端是否该面试算法的观点都在这篇文章《面试官:工作两年了,这么简单的算法题你都不会?》里面了。其中有一句:


技术题目无罪,不要让不好的面试体验干涉到技术学习上来。


是的,算法题是绝对有它本身价值的!


对算法感到畏惧的 xdm,咱不求一口吃个胖子,先对算法简单题重拳出击,尝试建立自信,训练基础算法思维,不日定能大杀四方、所向披靡。

OK,闲言少叙,上题:


这是一道经典题:# 剑指 Offer 42. 连续子数组的最大和


输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为O(n)。


示例1:

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


这题的基础算法思维是:动态规划(Dynamic programming,简称DP)

  • 老观众都知道之前在讲狄克斯特拉最短路径问题有提过这个,有兴趣去专栏翻一翻。


DP的操作过程,一言以蔽之:大事化小,小事化了。 即将一个大问题转化成几个小问题;求解小问题;推出大问题的解。


解:

1、题目要求的是给出连续最大子数组和是多少,而没有要求给出连续最大子数组是哪一个。明白这一点很重要。

2、其次,题目要求了,时间复杂度要是 O(n) ,所以只能用一次遍历。

3、接着,最关键的是,怎么理解“连续最大”。“连续最大数组的特点是什么?”


答案是:

  • 连续最大的数组的最后一位肯定是一个正数,要不然还把它纳入进来干嘛?
  • 然后,这个正数前面的几个数字之和也要是正数!要不然还要它前面的纳入干嘛?

有了上面的认识,我们用一层 for 循环,用 sum 变量来收集当前遍历的数字前面数字的最大和,如果这个最大和大于0,则加上当前遍历数字,如果这个最大和小于0,则让最大和直接等于正在遍历的数字。最终的结果 res 在上一轮的最大和和这一轮的计算后的最大和中取最大值。


比如数组是 [-2,1,3,-4,5]:res 初始值为 nums[0],即为 -2;

开始遍历:


[-2],sum = -2 res = -2

[-2,1] sum 在上一轮为 -2,小于 0 ,此时,最大和等于 1,供下一轮判断使用 ,res = max(-2,1)

[-2,1,3] sum 在上一轮为 1,大于 0,此时最大和等于 1+3=4,res = max(1,4)

[-2,1,3,-4] sum 在上一轮为 4 ,大于0,此时最大和等于 4-4=0,res= max(4,0)

[-2,1,3,-4,5] sum 在上一轮为 0, 等于0,此时最大和等于 0+5=5,res=max(4,5)


所以:

如果 sum > 0,则说明 sum 对结果有增益效果,则 sum 保留并加上当前遍历数字

如果 sum <= 0,则说明 sum 对结果无增益效果,需要舍弃,则 sum 直接更新为当前遍历数字

每次比较 sumres的大小,将最大值置为res,遍历结束返回结果


代码实现:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let res = nums[0];
    let sum = 0;
    for(const num of nums) {
        sum > 0 ? sum+=num : sum = num
        res = Math.max(res, sum);
    }
    return res;
};


小结:


本题,思路很重要。想明白给的条件的引申解释123点,再跟着示例去走一遍,代码中的 DP 思路就很好理解了~


相关文章
|
6月前
|
设计模式 算法 Java
【数据结构和算法】删掉一个元素以后全为 1 的最长子数组
这是力扣的 1493 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。又又又是一道滑动窗口的典型例题,可以帮助我们巩固滑动窗口算法。这道题很活灵活现,需要加深对题意的变相理解。给你一个二进制数组nums,你需要从中删掉一个元素。 请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。 如果不存在这样的子数组,请返回 0 。
110 1
|
6月前
|
算法
class071 子数组最大累加和问题与扩展-下【算法】
class071 子数组最大累加和问题与扩展-下【算法】
51 0
|
11月前
|
算法 测试技术 C#
C++前缀和算法的应用:统计中位数为 K 的子数组
C++前缀和算法的应用:统计中位数为 K 的子数组
|
3月前
|
算法
【算法】滑动窗口——长度最小的子数组
【算法】滑动窗口——长度最小的子数组
|
6月前
|
算法
|
3月前
|
算法 C++
【算法】前缀和算法——和可被K整除的子数组
【算法】前缀和算法——和可被K整除的子数组
|
3月前
|
算法
【算法】前缀和算法——和为k的子数组之和
【算法】前缀和算法——和为k的子数组之和
|
3月前
|
算法 Java
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
43 0
|
6月前
|
设计模式 算法 Java
【数据结构和算法】子数组最大平均数 I
​ 原题链接:力扣 643 题 子数组最大平均数 I 给你一个由n个元素组成的整数数组nums和一个整数k。 请你找出平均数最大且长度为k的连续子数组,并输出该最大平均数。 任何误差小于10-5的答案都将被视为正确答案。 ​
70 3
|
5月前
|
机器学习/深度学习 算法 测试技术
【算法优选】 动态规划之子数组、子串系列——壹
【算法优选】 动态规划之子数组、子串系列——壹