1. 程式人生 > >騰訊演算法筆試:2019/08/17

騰訊演算法筆試:2019/08/17

1. 修柵欄(連續k個子序列和最小)

輸入:
7 3
1 2 6 1 1 7 1

輸出:
3

說明:

從第三個位置開始拔欄杆拔掉的長度最小為8

分析:

  1. 這個題是變相的求解長度為k的連續子序列和最小時,序列的起始位置
  2. 需要注意的是:隨著遍歷,不斷變化的變數有:_sum:長度為k 的子序列的和, _min:只有符合條件時,才會變化
 1 import sys
 2 
 3 if __name__ == '__main__':
 4     n, k = map(int, sys.stdin.readline().split(" "))
 5     h = list(map(int, sys.stdin.readline().split(" ")))
 6 
 7     _min = sum(h[:k])
 8     flag = 1
 9     _sum = _min
10     for i in range(k, n):
11         _sum = _sum + h[i] - h[i - k]
12         if _sum < _min:
13             _min = _sum
14             flag = i - k + 2
15     print(flag)

 2. 小Q玩遊戲

輸入:
2
4 6
X...XX
...XX.
.X..X.
......
1 6
2 2
9 47
....X.X.X.X...X..X.....X..X..X..X....X.X...X..X
XX..X...X.........X...X...X..X.XX......X...X...
..XX...X.......X.....X.....X.XX..X.....X..XX...
.X...XX....X...X.......X.X...X......X.X.X......
X......X..X.XXX....X...X.X.XX..X.......X....X.X
....XX.X...X.XXX.X..XX.XXX...XXX..XX.X.X.XX..XX
.........X...X.XXXX...XX.XX....XX..X...X....X..
.............X....XXXX....X.X...XX.XX.X.X..X...
.X......X.....X......X......X.X.X..X.......XXX.
2 34
7 30


輸出:
YES
NO

分析:

  1. 題中:“.” 表示沒有被破壞的方塊,“X”:表示已經被破壞的方塊。已經被破壞的方塊走一次就會碎掉(不能再走了),沒有被破壞的方塊可以走2次。 為了方便,在輸入時做一個對映,maps = {".":2, ”X":1 }
  2. “.”:可以走兩次, “X”:只能走一次(不能再走了):即,當走到該位置時,如果 符號是“.” ,將“.” 更換成“X”, 繼續走;如果符號是“X”, 終止不能再走了。即,2 能走, 1不能走。
 1 import sys
 2 import numpy as np
 3 
 4 # 全域性變數:上右下左,橫縱座標的偏移量
 5 dx, dy = [-1, 0, 1, 0], [0, 1, 0, -1]
 6 
 7 # 找路徑
 8 def find(n, m, sig, begin, end, x, y):
 9     # 走到最後一個格子,並且踩碎
10     sig[x][y] -= 1
11     if x == end[0]-1 and y == end[1]-1 and sig[x][y] == 1: return True
12     # 開始上下左右搜尋
13     for i in range(4):
14         a, b = x+dx[i], y+dy[i]
15         if 0<= a < n and 0<= b < m and sig[a][b] == 2:
16             if find(n, m, sig, begin, end, a, b):
17                 return True
18     # 走到這,說明走不通(還原)
19     sig[x][y] += 1
20     return False
21 
22 if __name__ == '__main__':
23     nms, sigs, begins, ends = [], [], [], []
24     maps = {".": 2, "X": 1}
25     # 輸入
26     t = int(sys.stdin.readline().strip("\n"))  # t組測試
27     for i in range(t):
28         n, m = map(int, sys.stdin.readline().split(" "))
29         nms.append([n, m])
30         sig = []
31         for _ in range(n):
32             line = sys.stdin.readline().strip("\n")
33             sig.append(list(map(lambda i:maps[i], line)))  # 對映轉換
34         sigs.append(sig)
35         begins.append(list(map(int, sys.stdin.readline().split(" "))))
36         ends.append(list(map(int, sys.stdin.readline().split(" "))))
37     # 測試
38     for i in range(t):
39         n, m = nms[i]
40         sig = sigs[i]
41         # print("sig = \n{}".format(np.array(sig)))
42         begin, end = begins[i], ends[i]
43         if find(n, m, sig, begin, end, begin[0]-1, begin[1]-1):
44             print("YES")
45         else:
46             print("NO")

3. 冰激凌配料

輸入:

3 10
2 5 3
2 1 3

輸出:

4

說明:

# 4 (7)
# 5 (12)
# 6 (18)
# 7 (24)

 分析:

  1. 這題對時間複雜度有要求,如果只是單純的暴力求解的話,只能過20%
  2. 需要精簡中間計算和遍歷環節
  3. 則,將 w 和 v 按照數量 w 進行排序,從小到大開始累加

 

 1 def maxGet(money, goods, prices):
 2     get = min(goods)  # 現在儲存能成產的量
 3     goods = list(map(lambda x:x-get, goods))  # 更新庫存
 4     # 將goods, prices 按照庫存剩餘量排序
 5     goods, prices = zip(*sorted(zip(goods, prices)))  
 6     goods, prices = list(goods), list(prices)
 7     goods.append(float("inf"))  # 新增哨兵
 8     index = cost = 0
 9     while True:
10         # 補齊index和index+1之間的差距
11         gap = goods[index+1] - goods[index]  
12         cost += prices[index]
13         if gap * cost < money:
14             money -= gap * cost
15             get += gap
16             index += 1
17         else:
18             get += money // cost
19             break
20     return get
21 
22 import sys
23 if __name__ == '__main__':
24     n, m = map(int, sys.stdin.readline().split(" "))
25     w = list(map(int, sys.stdin.readline().split(" ")))
26     v = list(map(int, sys.stdin.readline().split(" ")))
27     print(maxGet(m, w, v))

4. 飛機航線

輸入:
3 5 3
1 2 7
2 3 6
1 3 9
2 1 2
3 1 1
1 2 3 8
2 3 3 1
2 1 3 5


輸出:
8
8
9

 分析:

我個人理解是:

  1. 建立一個n*n的關係矩陣arr,arr[i][j] 表示飛機從城市i直接飛往城市 j 的機票價格(即,帶權值矩陣---圖)
  2. 求解從城市1到城市n之間的最小距離
  3. 最小路徑問題的求解方法,一般有:迪傑斯特拉演算法、佛洛依德演算法、廣度優先遍歷。
  4. (目前程式碼還沒有完全除錯正確,後續補上程式碼環節)

5. 探險

輸入:
6
1 2 3
8 9 10
5 0 5
-9 -8 -10
0 1 2
5 4 6

輸出:
27

說明:
小Q走 3-> 10 -> 0 -> -9 -> 0 -> 5 這條路徑得到最高的分數,其中 -9 將取相反數,得 9 分

 分析:

  1. 遇見0,取相反數,這道題的最終目標是取最大,所以需要同時記錄opt_min和opt_max
  2. opt_max[ i ][ j ]:表示走到該位置最大的分數
  3. opt_min[ i ][ j ]:表示走到該位置最小的分數

 

 1 import sys
 2 import numpy as np
 3 import copy
 4 
 5 def maxScore(n, scores):
 6     # opt_max[i][j]:表示走到該位置最大的分數
 7     # opt_min[i][j]:表示走到該位置最小的分數
 8     opt_max = [[0 for _ in range(3)] for _ in range(n)]
 9     opt_max[0][:] = scores[0][:]  # 初始化起始位置
10     opt_min = copy.deepcopy(opt_max)  # 深層拷貝
11     for i in range(1, n):
12         # j = 0
13         if scores[i][0] == 0:
14             opt_max[i][0] = -min(opt_min[i-1][0], opt_min[i-1][1])
15             opt_min[i][0] = -max(opt_max[i-1][0], opt_max[i-1][1])
16         else:
17             opt_max[i][0] = max(opt_max[i-1][0], opt_max[i-1][1]) + \
18             scores[i][0]
19             opt_min[i][0] = min(opt_min[i-1][0], opt_min[i-1][1]) + \
20             scores[i][0]
21         # j = 1
22         if scores[i][1] == 0:
23             opt_max[i][1] = -min(opt_min[i-1][0], opt_min[i-1][1], \
24              opt_min[i-1][2])
25             opt_min[i][1] = -max(opt_max[i-1][0], opt_max[i-1][1],  \
26             opt_max[i-1][2])
27         else:
28             opt_max[i][1] = max(opt_max[i-1][0], opt_max[i-1][1], \
29             opt_max[i-1][2]) + scores[i][1]
30             opt_min[i][1] = min(opt_min[i-1][0], opt_min[i-1][1], \
31             opt_min[i-1][2]) + scores[i][1]
32         # j = 2
33         if scores[i][2] == 0:
34             opt_max[i][2] = -min(opt_min[i-1][1], opt_min[i-1][2])
35             opt_min[i][2] = -max(opt_max[i-1][1], opt_max[i-1][2])
36         else:
37             opt_max[i][2] = max(opt_max[i-1][1], opt_max[i-1][2]) + \
38             scores[i][2]
39             opt_min[i][2] = min(opt_min[i-1][1], opt_min[i-1][2]) + \
40             scores[i][2]
41     # print(np.array(opt_max))
42     # print(np.array(opt_min))
43     return max(opt_max[-1])
44 
45 
46 if __name__ == '__main__':
47     n = int(sys.stdin.readline().strip("\n"))
48     scores = []
49     for i in range(n):
50         scores.append(list(map(int, sys.stdin.readline().split(" "))))
51     print(maxScore(n, scores))

&n