面试 20:计算连续子数组的最大和(剑指 Offer 31 题)

面试 20:计算连续子数组的最大和(剑指 Offer 31 题)

我们上一次推文留下的题目来源于《剑指 Offer》第 31 题:计算连续子数组的最大和。

面试题:输入一个整型数组,数组中有正数也有负数。数组中一个或多个整数形成一个子数组,求所有连续子数组的和的最大值,要求时间复杂度为 O(n)。
比如输入 {1, -2, 3, 10, -4, 7, 2, -5},能产生子数组最大和的子数组为 {3,10,-4,7,2},最大和为 18。

准备测试用例

我们首先准备好测试用例,该题的测试用例也很简单。

  1. 输入错误的值,比如空数组或者空指针,应该抛出异常;
  2. 输入一个数组,数组包含正数和负数;
  3. 输入一个数组,数组全是正数;
  4. 输入一个数组,数组全是负数。

思考程序逻辑

看到本题,最直观的想法肯定是分出输入数组的所有子数组,并对它们一一求和,最后找到最大和对应的子数组。但一个长度为 n 的数组,总共都有 n(n+1)/2 个子数组,最快也需要 O(n2),所以显然不符合题目要求的 O(n) 算法。

我们再看题干,尝试从头到尾累加示例数组中的每个数字。

我们把和初始化和为 0。第一步加上第一个数字 1, 此时和为 1。接下来第二步加上数字 -2,和就变成了 -1。第三步加上数字 3。我们注意到由于此前累计的和是 -1 ,小于 0,那如果用 -1 加上 3 ,得到的和是 2 , 比 3 本身还小。也就是说从第一个数字开始的子数组的和会小于从第三个数字开始的子数组的和。因此我们不用考虑从第一个数字开始的子数组,之前累计的和也被抛弃。

我们从第三个数字重新开始累加,此时得到的和是 3 。接下来第四步加 10,得到和为 13 。第五步加上 -4, 和为 9。我们发现由于 -4 是一个负数,因此累加 -4 之后得到的和比原来的和还要小。因此我们要把之前得到的和 13 保存下来,它有可能是最大的子数组的和。第六步加上数字 7,9 加 7 的结果是 16,此时和比之前最大的和 13 还要大, 把最大的子数组的和由 13 更新为 16。第七步加上 2,累加得到的和为 18,同时我们也要更新最大子数组的和。第八步加上最后一个数字 -5,由于得到的和为 13 ,小于此前最大的和 18,因此最终最大的子数组的和为18 ,对应的子数组是 {3, 10, -4, 7, 2}。

我们还是用表格表示,可能会更加清晰。

步骤 操作 累加的子数组和 最大的子数组和
1 加 1 1 1
2 加 -2 -1 1
3 舍弃前面的 -1,加 3 3 3
4 加 10 13 13
5 加 -4 9 13
6 加 7 16 16
7 加 2 18 18
8 加 -5 13 18

表格后确实清晰太多了,可见 我们平时有想法不一定好写代码,但做了表格,思路绝对清晰的多。当然你是大佬,完全是可以舍弃表格建思路的。

用上面的这种思路写代码就是:

public class Test20 {

    private static int findTheNumOfSubArray(int[] nums) {
        if (nums == null || nums.length == 0)
            throw new RuntimeException("the length of input must be large than 0!");
        // 用 result 存放返回结果,即最大和
        int result = Integer.MIN_VALUE;
        // 用 sum 存放当前累加结果
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            // 如果小于 0,则直接说明不可能是从前面开始的。不加之前的值,直接算当前值
            if (sum < 0) {
                sum = nums[i];
            } else {
                // 如果大于 0,则相加
                sum += nums[i];
            }
            // 如果添加后的值大于之前存放的最大值,则更新最大值
            if (sum > result)
                result = sum;
        }
        return result;
    }


    public static void main(String[] args) {
        int[] nums1 = {1, -2, 3, 10, -4, 7, 2, -5};
        System.out.println(findTheNumOfSubArray(nums1));
        int[] nums2 = {1,2,3,4,5};
        System.out.println(findTheNumOfSubArray(nums2));
        int[] nums3 = {-1,-2,-3,-4 -5};
        System.out.println(findTheNumOfSubArray(nums3));
    }
}

分别测试测试用例,测试通过。

最后再说点题外的吧,不少人现在还在找我「模拟面试」,该项活动已经截止很久啦,虽然本宝宝的菜单入口依然还在,那只能说明南尘等空闲一点会继续开放的,所以敬请期待洛~

另外一点,南尘的号可能最近一段时间不会日更了,可能一星期,可能一个月,可能更长…但南尘不会辜负大家的陪伴~

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容

  • 今天是我进小灶群的第42天。 每天清晨,我会给大家通报一声“早上好”,并推送一篇昨日的晨读感悟。一天内,我一般发三...
    影子倒了阅读 593评论 24 25
  • 内部或外部存储 internal和external存储的名字来源于早期的Android设备,它提供了内置的非易失性...
    wangdy12阅读 379评论 0 0
  • 终于是下雪了。 这场雪来的似乎是有点晚,看着天气预报上全国各地的雪景秀,我们这几乎是被上帝遗忘的角落。前几周就连很...
    珺君和阅读 426评论 5 2
  • 悲夫!深夜失眠。头昏脑胀,痛不欲生。忆往思今,妄想未来。胡思乱想,徒自添堵。思想涣散,天马行空,信马由缰,不可控制...
    妖娆而生阅读 244评论 0 0
  • 我喜欢你,就像执手偕老的足迹,不远万里 我喜欢你,就像前世所患的旧疾,今生无医 我喜欢你,就像托风给你情话里,暗藏...
    小麦iii阅读 273评论 4 9