腾讯算法笔试: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))

 

posted @ 2019-08-18 23:27 JeannieLi 阅读(...) 评论(...) 编辑 收藏