京东笔试(离AK最近的一次,可惜)

首先就想吐槽下它那个破代码平台,真的烂想进去考试显示器缩放必须调成100%,不是哥我显示器缩放招你惹你了,因为用的是3k笔电屏,平时都是250%,调100之后整个系统ui小的跟蚂蚁似的眼睛都酸了

然后代码编辑器,真就是一张白纸,连main函数和导包都得自己写(好在右上角有个指南里面有个Demo,不然要是忘了Scanner要导那个包怕不是直接坐牢俩小时)。总之就是一坨,真的不如牛客

题目方面,算法就两个,没有签到题,第一题就上强度,第二题反而简单一些,因为它是利特扣德上题目《滑动窗口最大值》的变体,做过原型的话基本上就不难想

第一题是给个数组,可以进行一次操作:选定一个区间使得区间内的值都+1。要求尽可能使此操作减少最多数量的逆序对,并返回所减少逆序对的数目

乍一看一点思路都没有,因为光是求取一个数组的逆序对数量就已经是一个hard(参见LCR.170)难度了,这还不包括后面处理最大化收益的逻辑。所以这题坑就坑在它完全不给你暴力的机会。

但注意到题目要求返回的是操作所减少的逆序对的数目(比如原数组5个逆序对操作后变成3个则返回2),所以实际上并不需要求操作前后的逆序对数量分别是多少,只需考虑如何将“受影响的逆序对数量”最大化即可。依照题目,假如我们对区间[L, R]进行操作,则可以把数组分为三部分:[0, L - 1],[L, R],[R + 1, len(arr)]

而中间[L, R]这一段集体+1的操作,对其中每个的x∈[L, R],都会带来 a = count(y, y∈[0, L - 1] & y = x + 1) 个逆序对的减少,但与此同时也会额外增加 b = count(z, z∈[R + 1, len(arr)] & z = x) 个逆序对。而我们要做的是确定这样的一个区间,使 a - b 最大化

显然这样做非常困难,但这个问题是否可以简化一下呢?当然。实际上我们从一开始就掉入了这个题干中的陷阱。事实上并不用选择一个[L, R]区间来进行操作——我们完全可以在任何情况下都贪心地把L之后的元素全部选择:因为它们集体进行了+1,那么这个过程其内部就不会产生额外的逆序对。这样一来问题就简化为了,选定一个下标i,使得 count(i之前的元素 = i及其之后的元素 + 1) 最大化。

实现方面,朴素解法是对于每个下标i都去遍历一遍整个数组,全量计算满足条件的元素对个数,开销是n^2。这里可以使用两个HashMap去算增量,从而将时间开销优化至o(n)通过全部用例,关键部分代码如下:

public int f(int[] arr) {
  Map<Integer, Integer> leftNums = new HashMap<>();
  Map<Integer, Integer> rightNums = new HashMap<>();
  for (int i = 0; i < arr.length; i++) {
	int num = arr[i];
	rightNums.put(num, rightNums.getOrDefault(num, 0) + 1); // 一开始全部都在右侧集合
  }
  int ans = 0;
  int sum = 0;
  for (int i = 0; i < arr.length; i++) {
	int num = arr[i];
	rightNums.put(num, rightNums.get(num) - 1); // 元素离开右侧集合
	sum -= leftNums.getOrDefault(num + 1, 0); // 元素原先作为右侧集合元素被计算的逆序对数量被扣除
	leftNums.put(num, leftNums.getOrDefault(num, 0) + 1); // 元素进入左侧集合
	sum += rightNums.getOrDefault(num - 1, 0); // 计算右侧集合中比该元素小1的元素的个数
	ans = Math.max(ans, sum);
  }
  return ans;
}

第二题是给定一个数组和一个窗口长度,窗口的分值计算规则是:窗口内所有元素去掉一个最高分和一个最低分,其余元素的均值。返回分数最高的窗口的起始下标

这个就不想多做解释了,本质上就是滑动窗口最大值的变体,只是这次需要同时维护最大值和最小值,可以通过两个单调队列来实现。此外还需要增量式地维护每个窗口的总分,然后从两个队列中peek出最高分和最低分减去,再和历史最大值比较即可。注意窗口总分需要使用长整型避免溢出。代码比较冗长这里就不贴了,具体可以去利特寇德上看原型题

(不过不知道为啥我这里无论怎么提交都只过91%的用例,一直到交卷也没找出哪个边界case有问题,可能确实是有些细节没考虑到吧差一点就AK了)

#秋招笔面试记录##牛客创作赏金赛#
全部评论
你老是告诉我你就本科期间到底有没有打a
1 回复 分享
发布于 08-17 00:40 湖南
给♂✌🏻👻🌶️
点赞 回复 分享
发布于 08-18 11:49 上海
已老实
点赞 回复 分享
发布于 08-18 11:32 北京
第一题讲的很明白了
点赞 回复 分享
发布于 08-18 11:06 江苏
点赞 回复 分享
发布于 08-17 17:07 北京
太强了
点赞 回复 分享
发布于 08-17 17:01 北京
我也写了这道题能不能帮我看下我的思路对不对捏感谢大佬
点赞 回复 分享
发布于 08-17 15:43 内蒙古
第一题求出每个点对答案的贡献之后跑个最长连续子序列的和就行了吧,直接这样取max也行吗
点赞 回复 分享
发布于 08-17 01:30 北京
真牛逼啊
点赞 回复 分享
发布于 08-17 00:23 上海
猪神强
点赞 回复 分享
发布于 08-16 23:30 浙江
题目强度离谱
点赞 回复 分享
发布于 08-16 23:26 北京
这代码缩进在编辑界面是正常的,怎么一到浏览界面就乱了
点赞 回复 分享
发布于 08-16 22:39 北京

相关推荐

08-17 18:37
已编辑
四川大学 Java
居然ak了我靠,还睡过了晚了十分钟才开始做。暑期pdd笔试就零点几...1.从&nbsp;n&nbsp;个商品中选取两个商品,要求和为m的倍数,有多少种这样的商品组合直接哈希表。所有数对m取余,哈希表存相同余数数量,结果为两个余数相加为目的数时的数量之和2.每天都会有一只小动物来到你的农场&nbsp;,&nbsp;​​n&nbsp;天内每天会来一直小动物,可以选择留下或者赶走,留下需要给他们提供第i到n天的食物​​,每个小动物需要每天吃a数量的食物,再总消耗不超过总食物M的前提下,求第m天最多能有多少动物直接计算出所有动物需要消耗的食物,排序,每次取最小直到M为止3.从&nbsp;N&nbsp;个任务中,选出一个连续的区间,使得这个区间内所有任务的分数之和&gt;=&nbsp;T​​。而在这个窗口中的单个任务难度的最大值为这个窗口的难度​​。找到一个窗口,这个窗口的难度为所有窗口中难度最低的。只需要求出最小难度,不返回对应的窗口。优先队列+滑动窗口,类似于hot100里面的滑动窗口最大值,不同的是hot100是固定窗口大小,而这里是要窗口分数&gt;=T。不断向右移动右指针并加上分数,当总分数大于目的分数则取队头元素并移动左指针,如果队头元素在左指针范围外则poll出去4.在一条道路旁种了一排树,每棵树都有一个美观值。要求这条道路上任意一段连续的树的美观值之和都不能等于&nbsp;M。为了达到这个目标,可以在任意位置插入一棵任意美观值的树,求最少需要插入多少次新树,才能保证整条道路上不存在任何一段连续子序列的美观值和为&nbsp;M。就是找和为M的区间的交集有多少个,先前缀和然后滑动窗口
牛客42678573...:暑期 ak 了,这次只有 2.5
投递拼多多集团-PDD等公司10个岗位
点赞 评论 收藏
分享
评论
20
13
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务