京東實習生招聘題目解析(三)

有段時間沒寫了,可是以前把JD剩餘的題目基本仍是過了一次,題目整體都比較簡單,本次的解析選擇了其中的5個題目,因爲比較簡單,就分析的簡略些,留一些思考的空間。由於好久沒有更新,最近還會和你們討論一個動態規劃解決的簡單博弈問題。python


站隊

<題目來源: 京東2017秋招 原題連接-可在線提交(賽碼網) >面試

問題描述

一條很長的隊伍,隊伍裏面一共有n我的。全部的人分爲三類:警察,小偷和普通人。將隊伍裏面的人從前到後由1到n編號,編號爲i的人與編號爲j的人的距離爲i與j之差的絕對值。編程

每個警察有一個能力值x,表示他可以監視與他距離不超過x的全部人,小偷被警察發現當且僅當他被一個或多個警察監視到。你知道在整條隊伍中,一共有多少個小偷會被警察發現嗎?數據結構

clipboard.png

題目意思比較簡單,最容易想到就是掃描一次這個隊伍,若是是警察,就檢查其能力範圍內是否有小偷,若是有小偷就給小偷打上標記,這樣是爲了防止重複統計。當執行完本次掃描後就獲得了最後的結果。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()

第K個幸運數

<題目來源: 京東2017實習生招聘 原題連接-可在線提交(賽碼網) >排序

問題描述

4和7是兩個幸運數字,咱們定義,十進制表示中,每一位只有4和7兩個數的正整數都是幸運數字。前幾個幸運數字爲:4,7,44,47,74,77,444,447...

如今輸入一個數字K,輸出第K個幸運數。

clipboard.png

先按順序列出一些幸運數(下劃線是爲了從低位開始對齊):
___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的候選者,此外還有其餘的候選者參加選舉。根據初步的調查狀況,全部準備投票的小朋友都有必定的投票傾向性,小東若是要得到勝利,必須爭取部分準備爲其餘候選人投票的小朋友。

因爲小東的資源較爲有限,她但願用最小的代價贏得勝利,請你幫忙計算她最少須要爭取的選票數。

clipboard.png

要小東能獲勝,就要確保他本身的票超過另外全部人的票,就要從其餘的候選者那裏拿票。爲了儘量少的從其餘的人手中拿票,那麼應該儘量的從比他多且最多的人手中拿票。注意到拿票是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個合併委託。

clipboard.png

這個題目自己不難,可是必定要讀懂題意,該如何合併數據,該如何排序,如何取排序後的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進製表達時,各個位數之和的均值是多少?她但願你能幫她解決這個問題?
全部的計算均基於十進制進行,結果也用十進制表示爲不可約簡的分數形式。

clipboard.png

這個題目考察進制轉換,利用短除法能夠計算任何進制的轉換。此外,要掌握一到兩種最大公約數(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()
相關文章
相關標籤/搜索