有段時間沒寫了,可是以前把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()