有段时间没写了,可是以前把JD剩余的题目基本仍是过了一次,题目整体都比较简单,本次的解析选择了其中的5个题目,因为比较简单,就分析的简略些,留一些思考的空间。由于好久没有更新,最近还会和你们讨论一个动态规划解决的简单博弈问题。python
<题目来源: 京东2017秋招 原题连接-可在线提交(赛码网) >面试
一条很长的队伍,队伍里面一共有n我的。全部的人分为三类:警察,小偷和普通人。将队伍里面的人从前到后由1到n编号,编号为i的人与编号为j的人的距离为i与j之差的绝对值。编程
每个警察有一个能力值x,表示他可以监视与他距离不超过x的全部人,小偷被警察发现当且仅当他被一个或多个警察监视到。你知道在整条队伍中,一共有多少个小偷会被警察发现吗?数据结构
题目意思比较简单,最容易想到就是扫描一次这个队伍,若是是警察,就检查其能力范围内是否有小偷,若是有小偷就给小偷打上标记,这样是为了防止重复统计。当执行完本次扫描后就获得了最后的结果。app
观察题目的数据规模,n<=100000,而每一个警察能力值是1-9,最多须要扫描先后共计18我的。显然最坏状况下的运算也不过百万级,是彻底能够在1s内出解的。编码
那么咱们来思考下若是不限制警察的范围,那么这样作显然就不可行了。这样最坏状况能够是O(n^2),显然是可接受的。问题出在哪里呢?是因警察覆盖的范围出现了大量的重复。好比A警察在x=100的地方,B在x=110的地方,他们能力值都是100,显然对绝大多数位置进行了屡次扫描。spa
若是要提升程序效率咱们就要尽量的减小重复的扫描,那么咱们首先想到的是在加一个标记,表示当前扫描到了哪一个位置,下个警察再进行扫描时,若是扫描到了该位置就再也不继续扫描了。考虑下面的状况:
......------(1)------..............---(2)---........................
---------------------------(3)---------------------------
其中括号内的数字表示警察,"-"是其能力范围,..能够表示小偷或者普通人。rest
显然,记录最后扫描位置并非一种好的方法。咱们但愿找到因此警察能力值不重复覆盖的范围,联系到线段覆盖问题,又或者是流水线做业问题等,咱们获得一种处理方法,把每一个警察和其能力范围看作是一条线段,把全部的这些线段按左端点排序,而后依次处理右侧的值。考虑当前线段右侧的位置和下条线段左侧的位置便可。code
import sys def main(): n = map(int, sys.stdin.readline().strip().split())[0] line = list(map(str, sys.stdin.readline().strip().split())[0]) segments = [] for i, ch in enumerate(line): if '1' <= ch <= '9': t = int(ch) - int('0') left = max(0, i - t) right = min(n - 1, i + t) segments.append((left, right)) segments = sorted(segments, key=lambda s: s[0]) #print segments current = -1 res = 0 for segment in segments: if segment[0] <= current: l = current + 1 r = segment[1] else: l = segment[0] r = segment[1] for i in range(l, r + 1): if line[i] == 'X': res += 1 if r > current: current = r print res if __name__ == '__main__': main()
<题目来源: 京东2017实习生招聘 原题连接-可在线提交(赛码网) >排序
4和7是两个幸运数字,咱们定义,十进制表示中,每一位只有4和7两个数的正整数都是幸运数字。前几个幸运数字为:4,7,44,47,74,77,444,447...
如今输入一个数字K,输出第K个幸运数。
先按顺序列出一些幸运数(下划线是为了从低位开始对齐):
___4
___7
__44
__47
__74
__77
_444
_447
_474
_477
_744
_747
_774
_777
4444
...
观察规律发现:1位的2个,2位的4个,3位的8个,推测n位的幸运数有2^k个
再来观察低位规律 4, 7, 4, 7...
次低位的规律4, 4, 7, 7, 4, 4, 7, 7...
右侧第三位的规律,4, 4, 4, 4, 7, 7, 7, 7...
那么咱们就能够依靠这些规律来计算每一位的数字,须要注意的是在计算第k位的时候,前k-1位是须要去掉的。
第t个幸运数从低位开始第i位上的数字是r = (t - 2^i - 2) % 2^i
当 1 <= r <= 2^i / 2 时为'4',不然为'7'
import sys def main(): case = map(int, sys.stdin.readline().strip().split())[0] for c in range(case): n = map(int, sys.stdin.readline().strip().split())[0] sum2s = 1 num = [] while True: sum2s *= 2 if n - sum2s + 2 > 0: r = (n - sum2s + 2) % sum2s if 1 <= r <= sum2s / 2: num.insert(0, '4') else: num.insert(0, '7') else: break print ''.join(num) if __name__ == "__main__": main()
<题目来源: 京东2016实习生招聘 原题连接-可在线提交(赛码网) >
小东和其余小朋友正在玩一个关于选举的游戏。选举是经过投票的方式进行的,得票最多的人将获胜。
小东是编号为1的候选者,此外还有其余的候选者参加选举。根据初步的调查状况,全部准备投票的小朋友都有必定的投票倾向性,小东若是要得到胜利,必须争取部分准备为其余候选人投票的小朋友。
因为小东的资源较为有限,她但愿用最小的代价赢得胜利,请你帮忙计算她最少须要争取的选票数。
要小东能获胜,就要确保他本身的票超过另外全部人的票,就要从其余的候选者那里拿票。为了尽量少的从其余的人手中拿票,那么应该尽量的从比他多且最多的人手中拿票。注意到拿票是2个动做,小东会多一票,而被拿票的后选择会少一票。
问题就解法就是始终从票最多的人那里拿票(人会发生变化),直到本身的票数恰好成为最多的时候。
堆是一个能很好支撑这个要求的数据结构,若是不清楚堆(heap)能够查询相关资料。下面的代码使用了heapq来实现。
import sys import heapq def main(): while True: line = map(int, sys.stdin.readline().strip().split()) if len(line) < 0: break n = line[0] heap = [] line = map(int, sys.stdin.readline().strip().split()) for i, l in enumerate(line): if i: heapq.heappush(heap, -l) cnt = 0 while True: e = -heapq.nsmallest(1, heap)[0] if line[0] > e: break line[0] += 1 cnt += 1 e -= 1 heapq.heapreplace(heap, -e) print cnt if __name__ == '__main__': main()
<题目来源: 京东2016实习生招聘 原题连接-可在线提交(赛码网) >
金融证券行业超好的薪酬待遇,吸引了大批的求职者前往应聘,小东也不例外,准备应聘一家证券公司。面试官为考察她的数据分析、处理和编码能力,为她准备了如下问题。
股票交易中,委托是指股票交易者在证券公司买卖股票。每手委托包括一个委托单号i、价格pi、买入或卖出标记di及交易数量qi。
交易处理中,须要把同类业务(买入或卖出)中相同价格的全部委托合并起来,造成一个清单。清单的第一部分为按价格降序排列的合并后的卖出委托,紧随其后的是按相同顺序排列的买入合并委托。证券公司比较关心的是比较抢手的s条合并委托信息,须要获得买入及卖出最抢手的s条合并委托。对于买入委托,抢手的是指报价高的委托,而卖出委托中报价低的较为抢手。若买或卖的合并委托数小于s条,则所有列入清单中。
如今小东拿到的是n个委托,请你帮忙找出最抢手的s个合并委托。
这个题目自己不难,可是必定要读懂题意,该如何合并数据,该如何排序,如何取排序后的top n。这个题目能够锻炼快速编程的能力。
例如合并价格相同的委托,能够采用多种方式,我这里使用python,为了尽量的快速,使用了dict。而后分别再对买入和卖出的委托进行排序。
import sys def main(): while True: line = map(int, sys.stdin.readline().strip().split()) if len(line) < 2: break n, s = line[0], line[1] dict_b = {} dict_s = {} for i in range(n): line = map(str, sys.stdin.readline().strip().split()) if line[0] == 'B': r = dict_b.get(line[1]) if r is None: dict_b[line[1]] = int(line[2]) else: dict_b[line[1]] = r + int(line[2]) else: r = dict_s.get(line[1]) if r is None: dict_s[line[1]] = int(line[2]) else: dict_s[line[1]] = r + int(line[2]) list_b = [] list_s = [] for k, v in dict_b.iteritems(): list_b.append((int(k), v)) list_b = sorted(list_b, reverse=True) for k, v in dict_s.iteritems(): list_s.append((int(k), v)) list_s = sorted(list_s) p = min(s, len(list_s)) for e in list_s[p::-1]: print 'S', e[0], e[1] p = min(s, len(list_b)) for e in list_b[:p]: print 'B', e[0], e[1] if __name__ == '__main__': main()
<题目来源: 京东2017秋招 原题连接-可在线提交(赛码网) >
尽管是一个CS专业的学生,小B的数学基础很好并对数值计算有着特别的兴趣,喜欢用计算机程序来解决数学问题。如今,她正在玩一个数值变换的游戏。她发现计算机中常常用不一样的进制表示同一个数,如十进制数123表达为16进制时只包含两位数七、11(B),用八进制表示时为三位数一、七、3。按不一样进制表达时,各个位数的和也不一样,如上述例子中十六进制和八进制中各位数的和分别是18和11。
小B感兴趣的是,一个数A若是按2到A-1进制表达时,各个位数之和的均值是多少?她但愿你能帮她解决这个问题?
全部的计算均基于十进制进行,结果也用十进制表示为不可约简的分数形式。
这个题目考察进制转换,利用短除法能够计算任何进制的转换。此外,要掌握一到两种最大公约数(gcd)的计算方法。
import sys def gcd(a, b): c = a % b if c == 0: return b return gcd(b, c) def main(): while True: n = map(int, sys.stdin.readline().strip().split())[0] rest_sum = 0 for i in range(2, n): temp = n while temp: rest_sum += temp % i temp /= i g = gcd(rest_sum, n - 2) print("%d/%d" % (rest_sum / g, (n - 2) / g)) if __name__ == '__main__': main()