leetcode-WeeklyContest-102

来源:1-1 算法面试不仅仅是正确的回答问题

慕雪9091725

2018-09-16

波波老师,您好:
您一定参加今天上午的周赛了吧,我想问一下关于第三题子数组的最小值之和,当时做的时候用针对每个起点用动态规划的思路去遍历求最小值,算法的时间复杂度为O(N^2),超时了,下来看了好一会儿别人的代码,还是没看懂,您能给我简单的点拔下这道题的思路吗?谢谢您!

写回答

1回答

liuyubobobo

2018-09-17

以下简要说明基于我的代码:https://github.com/liuyubobobo/Play-Leetcode/blob/master/0907-Sum-of-Subarray-Minimums/cpp-0907/main.cpp


计算对于每一个A[i],有多少子集,其最小值是自己。

针对每一个A[i],求出比i大的最小索引j1,使得A[j1] <= A[i];

针对每一个A[i],求出比i小的最大索引j2,使得A[j2] < A[i];

则在子集[a, b]中,a可以取 j2 + 1 到 i 的任何值;b可以取 i 到 j1 + 1 的任何值,使得[a,b]这个子集的最小值都为A[i]。

这样的子集有 (i - j2) * (j1 - i) 个。

我们可以遍历一遍整个A,对每个A[i],直接计算出 (i - j2) * (j1 - i) * A[i],把他们加起来就好了。


==========


下面的关键是,如何高效的针对每一个A[i],求出比i大的最小索引j1,使得A[j1] <= A[i];以及针对每一个A[i],求出比i小的最大索引j2,使得A[j2] < A[i]。


这是一个经典的使用栈解决的问题。我建议看一遍901号问题。完全是这个子问题。https://leetcode.com/problems/online-stock-span/description/

(只不过这个问题是找到最靠近当前点的,比当前点还要大的数字的位置。)


经典的42题,也可以使用类似的思路解决:https://leetcode.com/problems/trapping-rain-water/description/


我不太有信心用比较简短的语言把这个思路阐述出来。整体我们在栈中维护了一个当前所能寻找的递增序列(也可能是递减序列,根据题意来定),每当有一个新元素来临,一旦这个元素比栈顶元素小(也可能是大,根据题意来定),我们就解决了栈顶元素的问题。以此类推。


如果对这个问题不熟悉,我建议以901号问题为例,先自己用最朴素的思想写出一个解,然后对于提交产生的错误用例,仔细理解自己的算法为什么不work,再仔细跟一遍答案代码的逻辑。体会一下答案代码为什么work。这个过程可能要重复几轮,才能比较透彻的彻底理解这个算法。(我的901号问题参考代码:https://github.com/liuyubobobo/Play-Leetcode/blob/master/0901-Online-Stock-Span/cpp-0901/main.cpp


加油!:)

1
3
慕雪9091725
非常感谢!
2018-09-17
共3条回复

玩转算法面试-- Leetcode真题分门别类讲解

课程配套大量BAT面试真题,高频算法题解析,强化训练

7408 学习 · 1150 问题

查看课程