字节跳动2019万万没想到之抓捕孔连顺

字节跳动2019万万没想到之抓捕孔连顺

话不多说先放题
[编程题]万万没想到之抓捕孔连顺
时间限制:1秒
空间限制:131072K
我叫王大锤,是一名特工。我刚刚接到任务:在字节跳动大街进行埋伏,抓捕恐怖分子孔连顺。和我一起行动的还有另外两名特工,我提议

  1. 我们在字节跳动大街的N个建筑中选定3个埋伏地点。
  2. 为了相互照应,我们决定相距最远的两名特工间的距离不超过D
    我特喵是个天才! 经过精密的计算,我们从X种可行的埋伏方案中选择了一种。这个方案万无一失,颤抖吧,孔连顺!
    万万没想到,计划还是失败了,孔连顺化妆成小龙女,混在cosplay的队伍中逃出了字节跳动大街。只怪他的伪装太成功了,就是杨过本人来了也发现不了的!
    请听题:给定N(可选作为埋伏点的建筑物数)、D(相距最远的两名特工间的距离的最大值)以及可选建筑的坐标,计算在这次行动中,大锤的小队有多少种埋伏选择。
    注意:
  3. 两个特工不能埋伏在同一地点
  4. 三个特工是等价的:即同样的位置组合(A, B, C) 只算一种埋伏方法,不能因“特工之间互换位置”而重复使用
    输入描述:
    第一行包含空格分隔的两个数字 N和D(1 ≤ N ≤ 1000000; 1 ≤ D ≤ 1000000)
    第二行包含N个建筑物的的位置,每个位置用一个整数(取值区间为[0, 1000000])表示,从小到大排列(将字节跳动大街看做一条数轴)
    输出描述:
    一个数字,表示不同埋伏方案的数量。结果可能溢出,请对 99997867 取模
    输入例子1:
    4 3
    1 2 3 4
    输出例子1:
    4
    例子说明1:
    可选方案 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)
    题目地址:https://www.nowcoder.com/question/next?pid=16516564&qid=362290&tid=27344590

解题思路

首先是我的解题思路,看到这个题目,最简单也是最暴力,肯定就是遍历全部可能性,然后排除掉不正确的可能性(这个排除可以单独写一个方法,对吧,学会安排轮子)
暴力解法思路:
参数 :N数量,D最大距离,一堆数(数组)
1.先把这堆数依次放到length为N的数组里
2.然后就是遍历全部可能性,就是获取数组中,全部的3个数的组合(三个for循环即可)
3.然后就是编写一个方法判断这些可能性可不可行了(其实一个if就可以完成了)
下面代码展示:
在这里插入图片描述

上面就是比较直观的解决方法,因为我比较讨厌写输入输出,所以以上demo无法通过测试,但是思路应该是没问题的,对了,上面没有考虑溢出和耗时,所以下面。

脑洞时刻

我突然想到,上面是列举所有的可能性,然后逐个排除,那么优化的方案,或者说,另一种解决方案就是找到正确的可能性(下面统称馄饨)的特点,然后找到它们,或者找出不正确的可能性(以下统称云吞)的特点,然后把总数-云吞=馄饨。
那么问题来了,馄饨的特点明显些还是云吞呢,一下子肯定都不知道嘛,来
我们一个一个地总结比较,先来总结馄饨的特点(特点:别人没有的点)
馄饨:三个数,相减小于D
云吞: 至少有两个数相减>D

nums[k]-nums[j]<D&&nums[j]-nums[i]<D&&nums[j]-nums[i]<D

这个式子就是表示的馄饨(正确)
这样看可能,你还没看透,那么我把云吞的式子放出来

nums[k]-nums[j]>D||nums[k]-nums[i]>D

下面,我们来实际应用一下两条式子,因为云吞(错误)的数量刚好就是nums[k]-nums[j]加上D||nums[j]-nums[i]>D
那么我们分别算一下,这两个式子
第一条
不用分别了,我算着算着,发现,这两个是一样的,就是下面的代码
在这里插入图片描述

图中的红线,我觉得是关键,就是当你的两个已经大于D时,你的第三个数有多少个可能性,就是例如②-①>D,那个第三个数可以是三,四,五,那么nums.length-j-1就是第三个数的可能性了。

算出云吞的数量了,下面就是算总数,这个不就是数学里(n*n-1*n-2)/1*2*3对吧,如果我没记错的话

总结一波,首先,第二次是优化了一些,但是没有确定耗时和考虑溢出,我现在想一下,好像还这样优化一下下,就是第二个for循环里,从右往左循环,当d<D时,就直接退出循环,这样会更棒一些,代码就不贴了吧,已经00:11了,狗命要紧,告辞

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值