【刷題】阿里20200330筆試

目錄

第1題

第2題

總結


第1題

小強有n個養雞場,第i個養雞場初始有a[i]只小雞。與其他養雞場不同的是,他的養雞場每天增加k只小雞,小強每天結束都會在數量最多的養雞場裏賣掉一半的小雞,假如一個養雞場有x只雞,則賣出後只剩下x/2(向下取整)只雞。問m天后小強的n個養雞場一共多少隻小雞?

  • 輸入

    第一行輸入三個int類型n,m,k(1 <= n,m,k <= 10^6)

    第二行輸入n個正整數,表示n個養雞場初始雞的個數

  • 輸出

    輸出一個整數表示雞的總數

  • 示例

    輸入:

    3 3 100

    100 200 400

    輸出:

    925

最後幾分鐘A了,很慌張。要點:

0 每天要選最大值 -> 數據結構使用大頂堆(優先隊列)

1 不能去更新隊列裏面的每個數值(否則必tle),隊列裏每個數都與實際值相差了i*k (i爲天數)

2 每天的最大值出隊後 賣掉一半 入隊的時候數值計算公式很關鍵:(max_-i*k)//2

計算公式是怎麼來的呢?

出隊得到假數值裏的max -> 恢復到真數據 -> 減少一半 -> 再減去偏移量(恢復到假數值)

即 ( max_+i*k )//2 - k*i  變換後得到 ( max_ - i*k )//2 

畫個圖解釋一下 【隊列裏每個數都與實際值相差了i*k (i爲天數)】

在實現上,由於python只有小頂堆(headq/queue.PriorityQueue),所以去負數來實現選擇最大值 即每次入隊時取負、 ( max_ - i*k )//2 裏的 - i*k  變成  + i*k

import sys
line = sys.stdin.readline().strip()
n, m, k = map(int, line.split())
line = sys.stdin.readline().strip()
a = list(map(int, line.split()))

from queue import PriorityQueue
q = PriorityQueue()
for i in a:
    q.put(-i) #入隊時都取負

for i in range(1, m + 1):
    max_ = q.get()
    tmp= (max_ + k * i) // 2 #  - i*k 變成 + i*k
    q.put(tmp)

print(-sum(q.queue) + n * m * k) #隊列裏n個假數據都和真數據相差了m*k 

長度爲n的優先隊列,每次維護的複雜度是logn;一共取了m次最大值、修改堆 故時間複雜度爲O(mlogn)

第2題

先暴力一手 例子能過 提交一直報錯

交完之後發現是沒有考慮輸入數組爲空的情況 導致分母會是0 不過照這次筆試的尿性 就算考慮了八成也是0分 這個題暫時沒怎麼想

題目描述:

總結

真是慌了神了 因爲習慣是每道題先無腦暴力試水 然後兩道題一直都是0分 搞得我一直以爲自己哪裏寫錯了 光輸入改了好幾次 最後還是例子沒錯但提交雙0 心態崩了 

緩一緩 從暴力想到了幾次優化:1使用優先隊列 減少每次取max的複雜度 2不能每天都更改隊列中所有數值,隊列裏每個數都與實際值相差了i*k 趕緊根據150=400-250寫出了公式max_-(max_+i*k)//2 變換後和前面寫的是一致的 最後幾分鐘A了 幸虧公式一找就找對了 要不然gg 與阿里無緣了 連面試都進不去 可真是太菜太丟人了

 

tips:

python中headq和queue.PriorityQueue的異同?

1 PriorityQueue保證線程安全 heapq 8星

2 PriorityQueue是對heapq的部分封裝 也就是說PriorityQueue就用heapq實現的

 

參考資料:

https://www.nowcoder.com/discuss/396281?type=1

https://www.nowcoder.com/discuss/396031

https://stackoverflow.com/questions/36991716/whats-the-difference-between-heapq-and-priorityqueue-in-python

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章