看到这个标题我就忍不住点进来了——“大姨的最高分数”。一看就是那种算法群里流传出来的接地气题名,前缀和加long long,两个关键词直接写在标题里,生怕别人不知道这题的坑在哪。实际上这道题的核心根本不是它的故事外壳,而是要求你读懂“前面所有数中的某个数”到底在说什么,然后顺手把答案类型开成long long。我先把完整题面给大家还原一下,再把思路和代码一步步拆开讲。
题目背景大概是这样的:LL老师带娃爬山,路上坑坑洼洼,她看到当前位置比前面所有位置都低的时候,就把这个坑填到前面没有比它更高的位置为止,然后再往前走。下山之后她把这个过程抽象成了一个算法题。题面是:给定n个数,第i个数是a_i,还有一个整数m,初始值是0。对于每个a_i,如果它比它前面的所有数中的某个数小,那么就把a_i和m同时加上1。最后问你m是多少。
这题看起来很绕,实际上翻译成人话就是:从左往右扫一遍,数一数有多少个元素,它小于它左边的某个元素。如果你能把这个条件想清楚,后面的优化就顺理成章了。
1. 先把题目读明白:大姨填坑的故事到底想说啥
1.1 故事背景与题面还原
很多算法题都爱套一个生活场景,这道题也一样。爬山路上遇到坑,把坑填到前面没有更高的位置,这本质上就是在维护一个“当前已经见过的最大高度”。当你站在一个新位置,发现它低于前面某一个位置,那这个坑就得填,填到前面最高点那么高,否则就不需要填。回到题面上,这个“填坑”动作被抽象成:如果a_i比前面的某个数小,则a_i和m同时加1。
注意这里的“同时加上1”其实是一个干扰项。a_i加1只是故事里“把坑填高”的具象化操作,它并不会影响后续的比较逻辑,因为后面比较的是原始的a数组,而不是填高之后的值。所以这个条件等价于:如果a_i小于max(a_1, a_2, ..., a_{i-1}),那么计数加一。
这个转化是整个题目的第一个关键点。如果你在考试或者比赛时没有看出来“前面所有数中的某个数”就是“前缀最大值”,那么很容易写出一个暴力双重循环,然后在一个大数据的测试点上超时。但一旦看出来,这题就变成了一个简单的线性扫描题。
1.2 拿一组样例手算一遍
光说不练假把式,我随手造一个样例,比如数组是[3, 1, 4, 2, 5]。我们手动模拟一遍,感受一下这个过程。
初始时m=0,前缀最大值mx初始为第一个数3。然后从第二个数开始扫:
- i=2,a=1,1小于3,所以计数m加1,m变成1,此时mx不变,仍然是3。
- i=3,a=4,4不小于3,所以不计数,mx更新为4。
- i=4,a=2,2小于4,计数m加1,m变成2,mx保持4。
- i=5,a=5,5不小于4,所以不计数,mx更新为5。
最终m=2。也就是说,在[3, 1, 4, 2, 5]这个序列里,有2个数(1和2)各自小于前面的某个数。
再验证一个边界样例,比如严格递增序列[1, 2, 3, 4, 5]。从头到尾,每个数都大于等于前一个数,所以mx一直在更新,m始终为0。这很合理,因为递增序列中不存在某个数比前面的某个数小。
再看严格递减序列[5, 4, 3, 2, 1]。初始mx=5,第二个数4小于5,计数加1;第三个数3小于5,计数加1;依此类推,最后m=4。这也很直观,除了第一个数,其余所有数都比第一个数小,所以答案是n-1。
1.3 一句话概括题目本质
这一节其实就是帮你提炼核心。
