騰訊暑期實習常規批筆試技術研究與資料分析卷程式設計題
2019騰訊暑期實習常規批筆試技術研究與資料分析卷程式設計題
- 題一 數字拆分
-
- 解題思路
-
- 注意點
- 解析
- python實現
- 程式碼解釋
- 題二 水果運費
-
- 解題思路
-
- 注意點
- 解析
- python實現
- 程式碼解釋
- 題三 找最小數
-
- 解題思路
-
- 注意點
- 解析
- python實現
- 程式碼解釋
題一 數字拆分
一個數字有兩種操作,1 對所有數字減一 2 把所有數字都拆分成兩個更小的數之和,問最多拆分K次,把N完全消去最少需要多少輪操作。
輸入取值範圍: 1<= N <=100, 0<=K<=100
樣例: 輸入 5 2 ,輸出 4。 輸入15 4,輸出 6
注:這裡其實第二個用例錯了, 因為5次就能完全消去。
解題思路
注意點
- 拆分操作是 所有 數字拆分,減一也是 所有 數都減。
- ~~把N完全消去 最少 需要多少輪操作。(廢話) ~~
解析
- 因為是所有數字同時拆分且所有數字同時減1,所以達到完全消去只需要保留過程中最大的數字即可,不需要完全模擬。
- 因為反正都是要消去,但是要找 最少 操作次數我們要比較這次消去前要不要拆分比較好。
python實現
# -*- coding: utf-8 -*- """ Created on Sun Apr 7 20:28:10 2019 @author: Ang """ def f(a, k): if k==0: return a a1 = a if a%2==0: a = a/2 else: a = a//2+1 a2 = f(a,k-1)+1 return a1 if a1<a2 else a2 x = list(map(int,input().split(' '))) a = x[0] k = x[1] print(int(f(a,k)))
程式碼解釋
f(a,k) 表示數字a在k次拆分機會的條件下最少需要幾次能被完全消去。
若不拆分直接消去 ,則為方案一的答案a1,為a次操作。
若拆分再接著消去 ,則為方案二的答案a2,我們先把a拆分,且為了消去操作次數最小肯定是對半拆分,保留 最大
的數字b即可,計算方案二的拆分次數f(b,k-1)+1。
兩種方案選擇最小的操作次數返回。
題二 水果運費
一條筆直的公路上有n個村莊,每個村莊有A[i]個水果,A[i] >0 代表 村莊需要購進水果, A[i] < 0 代表村莊需要賣出水果。
所有村莊供需平衡,即所有A[i]求和為0,把k個水果搬到相鄰村莊需要k塊錢的運費,
最少需要多少花費可以滿足所有村莊對水果的需求。
輸入取值範圍: 2 <= n <= 300000, -1000 <= A[i] <= 1000
樣例:
輸入
5
5 -4 1 -3 1
輸出
9
解題思路
注意點
- 一條筆直的公路 有n個村莊。
- 把k個水果搬到 相鄰 村莊需要k塊錢的運費
- 所有村莊 供需平衡 。
解析
- 表示所有村莊在同一維度上,沒有複雜的兩兩關係,降低問題難度。
- 從貪心的角度上,若從左往右考慮,最左的需求村莊從最左的供應村莊進貨肯定會是全域性最優解,因為最左的供應村莊往更右的需求村莊運水果會有更高的運費。
- 比如從左向右考慮,前i個村莊的供需若不平衡,肯定會繼續向右運水果或進水果而 產生更多費用 ,若平衡則 不產生更多費用 。所以我們只需要從左往右或從右往左把運費理一遍即可。
python實現
# -*- coding: utf-8 -*-
"""
Created on Sun Apr 7 20:51:03 2019
@author: Ang
"""
N = eval(input())
x = list(map(int,input().split(' ')))
ans = x[0]
for i in range(1,N):
x[i] += x[i-1]
ans += abs(x[i])
print(ans)
程式碼解釋
x[i] 表示要平衡前i個村莊的供需,還要供/需多少水果(其絕對值就是運費)。
就從頭到尾從左到右把運費理一遍即可。
注:這是我下來後才整理出來更簡單的方法,當時我的做法是給了兩個index(i,j),i表示最左的還需要水果的村莊,j表示最左的還可以提供水果的村莊,從左往右滿足需求的理了一遍運費,也是AC。
下來整理的這個方法當時有點靈感但是寫出來一個錯誤的,當時為了找出錯誤在哪浪費了大量時間導致很簡單的第三題沒有時間完成。太傻了
題三 找最小數
一天,小Q得到了一個包含n個數字的陣列,他想對這個陣列進行K次如下的操作。首先找出陣列中最小的非0數字X,輸出它,然後把陣列中的所有非零數字都減去X;如果陣列中的數字都是0,那麼直接輸出0。
輸入描述
第一行兩個數字n和k,用一個空格分隔
第二行n個數字,每兩個數字之間用一個空格分隔
滿足1<=n,k<=10 5 陣列中所有的數字ai滿足1<=ai<=10 9
樣例:
輸入
4 1
5 5 7 2
輸出
2
輸入
2 2
4 6
輸出
4
2
解題思路
注意點
- 找出陣列中 最小 的 非0 數字X。
- 把陣列中的所有 非零 數字 都 減去X。
- 這個陣列 進行K次 如下的操作。
解析
- 只找最小的非零數字。
- 為0的數字永遠為0了。大小順序不變。
- 只進行k次。意味著我們排序後,只需要對前面的部分數字進行處理,不需要全部處理。
python實現
# -*- coding: utf-8 -*-
"""
Created on Sun Apr 7 21:16:43 2019
@author: Ang
"""
x = list(map(int,input().split(' ')))
n = x[0]
k = x[1]
A = list(map(int,input().split(' ')))
def f():
global A
global k
A.sort()
i = 0
s = 0
while k:
while A[i]==s:
i+=1
if i>=n:
return
print(A[i]-s)
s+=(A[i]-s)
k-=1
f()
for i in range(k):
print(0)
程式碼解釋
首先我們把list A進行從小到大排序。
i 表示當前考慮的數字。 s 表示當前已減去的數字和。
只需要考慮當前A[i]是不是等於s即可,若 等於 ,表示A[i]已被減到0;否則輸出 A[i]-s 即可。不用實際的把所有數都減一遍。
若i超過了n(數字總個數),表示已經沒有更小的非0數字了,需要補剩餘輪次的0。