9.26阿里后端笔试第3题,解题思路

题目:
给定一个长度为n的数组{a1,a2,a3,..,an},定义一个操作:每次选择一个数x,使数组中所有x变成x+1,问至少需要多少次操作,才能得到非降数组

数据范围:
1<=n<=2*10^5;
1<=ai<=10^9

示例:
输入
2,5,3,4,9,7
输出
4

说明:
step 0:    2,5,3,4,9,7
step 1:    2,5,4,4,9,7
step 2:    2,5,5,5,9,7
step 3:    2,5,5,5,9,8
step 4:    2,5,5,5,9,9

思路:
首先想明白一个性质:如果数组已经是(非严格)单调的,那无论怎么操作都不会改变这种单调性。
其次,要保证操作尽可能少,那么就不能有重复操作,比如我们让数组中某个x变成x+1这种操作出现了两次,那肯定有一次是多余的,需要调整操作次序,让一次操作之后,再也不可能出现重复的操作;因此我们尽可能去对数组的最小值操作就行了。

流程:
(1)找到整个数组{a1,a2,a3,..,an}的最小值,如果有多个最小值,找最右边那个,假设是ai
(2)根据ai位置把原数组划分成左右两个数组{a1,a2,a3,...,ai}和{ai+1,ai+2,...,an}
(3)在左侧数组中,如果它的最大值是max,那么至少要对ai这个数做(max - ai)次操作,让它不断递增,才能让ai的大小不会小于左侧数组的任何一个值,这是左侧数组非降的必要条件
(4)在完成第(3)步的时候实际上导致了左侧数组最小值和最大值都变成了max ,它是常数列,已经满足了非降的条件,根据之前提到的性质,左侧数组的单调性已经不会改变了,那我们只需要再来研究右侧数组就好
(5)对右侧数组的处理只需要从第(1)步开始重复上面的操作就行,只是要注意之前第(3)步的操作已经改变了右侧数组的值,原来右侧数组里小于max的值都变成了max,其他值保持不变

数据结构:
(i)流程第(1)步要求当前数组的最小值,由于循环过程中,我们不断把数组向右侧“收缩”,那么用一个最小堆来维护数组里的值就行,再用一个hashtable来记录数组中每一个值最右侧的下标位置,这样第(1)步每次的复杂度就是log(n);
(ii)流程第(3)步要在左侧数组中找最大值,那么在流程之前应该先得到一个“前缀最大值”数组,这样每次只要O(1)的时间就能完成查找,由于第(3)步只会把左侧数组全部变成max,而max本身是不变的,所以这个数组不需要去维护;
(iii)在处理完左侧数组,准备处理右侧数组的时候,需要对hashtable[max]更新,因为现在所有小于max的值都变成了max;一边从堆里pop一边更新就行,pop完再判断一下现在最靠右的max是不是在右侧数组,如果在就把一个max再放回堆里。

所有的操作数都在第(3)步的max - ai里,时间复杂度主要来自于堆操作O(nlogn)
全部评论
感觉O(n)就可以?先找到最小值,再找到最小值左边的最大值,再对右半边重复操作就行了?
点赞 回复 分享
发布于 2022-09-27 07:41 上海
第二题思路有吗...
点赞 回复 分享
发布于 2022-09-27 07:42 上海
同学同花顺尝试一下吗,面试简单不造火箭,可保姆式全程跟进度,我帖子有内推
点赞 回复 分享
发布于 2022-09-27 09:34 浙江
优化一下,O(n)算法: 流程一样,数据结构上不用堆来找最小值了,因为我们每次找最小值是向右侧一直找到数组末尾,那只需要用一个数组记录一下每个位置上后缀数组的最小值就行。 算法流程开始前,先从前向后遍历得到前缀最大值数组,再从后向前遍历得到后缀最小值数组,顺便用hashtable记录每个值在数组中的下标(重复的时候记录最右边那个) 每次找数组最小值的时候,直接去找后缀最小值,如果它比之前已经归入非降数组部分的max还要小,那么它肯定由于之前的操作递增到了max非降,那最小值就是 max非降,否则就是后缀最小值里记录的那个值。后面操作完成,将左侧数组归入非降数组部分的时候,还要遍历左侧数组更新一下hashtable。 整个过程遍历数组3次,O(n)
点赞 回复 分享
发布于 2022-09-27 09:38 浙江

相关推荐

昨天 17:22
已编辑
西安交通大学 Java
华为 昇腾 ai软件开发 薪资20k x (14-16),职级13A,5%公积金,c/cpp
BLOOMING7:闭眼滴滴,华子给的又少又累
点赞 评论 收藏
分享
11-08 16:53
门头沟学院 C++
投票
滑模小马达:第三个如果是qfqc感觉还行,我签的qfkj搞电机的,违约金也很高,但公司感觉还可以,听说之前开过一个试用转正的应届生,仅供参考。
点赞 评论 收藏
分享
11-06 10:58
已编辑
门头沟学院 嵌入式工程师
双非25想找富婆不想打工:哦,这该死的伦敦腔,我敢打赌,你简直是个天才,如果我有offer的话,我一定用offer狠狠的打在你的脸上
点赞 评论 收藏
分享
评论
2
4
分享
牛客网
牛客企业服务