2018/4/15今日头条笔试题解

并没有参加,但是在讨论区看到题了,写写题解吧。
A:
考虑到问题实际上就是要求最小的k使得a[i] + T = a[i + k - 1],T = a[k] - a[1];
会发现问题也就是找(a[1] + T,a[2] + T,...a[n - k + 1] + T) == (a[k],a[k + 1],...,a[n])
我们发现在这两组数里面他们的差分序列是相等的。所以可以得出解法
构造一个差分序列c[i] = a[i + 1] - a[i].
问题就相当于求c[1....n - k] == c[k....n - 1]了,这里可以kmp来求

B:
简单的多重背包+0/1背包
dp[i][j]表示前i个物品凑成了面值为j的方案
dp[0][0] = 1;
对于可以无限用的物品来说,最朴素的做法就是
for(int i = 1; i <= n; i++)
for(int j = 0; j <= m; j++)
for(int z = 0; z * a[i] <= j; z++)
dp[i][j] += dp[i - 1][j - z * a[i]];
数据不水的话这东西肯定tle
但是注意到对于dp[i][j]来说实际上它加的是一个前缀和一样的东西..dp[i - 1][j] + dp[i - 1][j - a[i]] + dp[i - 1][j - a[i] * 2]....;
大概你已经发现了都是关于a[i]的这样一个式子,
如果我们在做这个i的dp之前先统计出tmp[j] = tmp[j - a[i]] + dp[i - 1][j];
于是
for(int i = 1; i <= n; i++){
for(int j = 0; j <= m; j++)tmp[j] = (j - a[i] >= 0 ? tmp[j - a[i]] : 0) + dp[i - 1][j];
for(int j = 0; j <= m; j++)dp[i][j] = tmp[j];
}
多重背包的方案做完。
01背包的很简单就不用写了。
这里没写取模。
实际上只要写出朴素dp之后就很容易发现这个优化。

C:
预处理出从起点开始走到i的往四个方向最远的max,然后直接二分答案

D:维护一个优先队列,里面是这样的信息A:分母下标,B当前的分子下标,C分母/分子
重载<号比较C的大小,然后对于i > 1,都把{ A(i),B(i - 1),C( a[i] / a[i - 1 ]) }丢进优先队列,每次取出最小值pop出来,并且加入{ A(A),B(B - 1),C(a[A]/a[B - 1]) },重复k次就是答案了。

E:
这题并不会证明,猜一发结论,有c % gcd(a,b) == 0时才有答案,并且总是一个瓶子往另一个瓶子倒水,也就是求a * x - b * y == c || b * x - a * y == c 的最小正整数解,然后答案就是2 * (x + y) - 2
(这题比较不确定,因为我是bfs跑几组数据,然后手推一下猜出来的答案)。
#春招##笔试题目##字节跳动#
全部评论
点赞 回复 分享
发布于 2018-04-16 17:19
做得很好了,我再为LZ补充一下E: 无解还有一种情况是c比a、b都大。 当c在a、b之间时,最后计算步数有时不用再-2,最后还要注意c等于a、b之一的case就好啦
点赞 回复 分享
发布于 2018-04-15 21:55
出来看神仙
点赞 回复 分享
发布于 2018-04-15 22:52
我后来想想,第三题不用二分,直接可以索引到,因为是连续的。
点赞 回复 分享
发布于 2018-04-15 23:00
对不起我不知道你这么叼.jpg
点赞 回复 分享
发布于 2018-04-16 02:25
围观巨佬
点赞 回复 分享
发布于 2018-04-16 10:02
大佬有没代码参考一下
点赞 回复 分享
发布于 2018-04-16 10:41
D题的解法还有个N的复杂度,g(素数个数)个有序数组求第K小复杂度是K*log(g),最终复杂度是N*K*log(g),复杂度应该不够。。g个有序数组求第K小还有种g*log(K)的做法,可是复杂度好像还是不够。
点赞 回复 分享
发布于 2018-04-18 13:34

相关推荐

像好涩一样好学:这公司我也拿过 基本明确周六加班 工资还凑活 另外下次镜头往上点儿
点赞 评论 收藏
分享
评论
点赞
37
分享
牛客网
牛客企业服务