【算法训练营】 - 顺丰科技智慧物流校园技术挑战赛
中国时间:2022-06-19 17:00 2 小时
1. 顺丰鄂州枢纽运转中心环线检测
【问题】
请帮忙检测线路上是否存在环形通路。
示例 1:
输入:“1->2,2->3,3->1”
输出:true
示例 2:
输入:“1->4,2->5,3->6,3->7,4->8,5->8,5->9,6->9,6->11,7->11,8->12,9->12,9->13,10->13,10->14,11->10,11->14”
输出:false
示例 3:
输入:“1->4,2->5,3->6,3->7,4->8,5->8,5->9,6->9,6->11,7->11,8->12,9->12,9->13,10->6,10->13,10->14,11->10,11->14”
输出:true
解释:存在环线:6->11,11->10,10->6
提示: 0 < 节点数 < 100
class Solution:
def hasCycle(self, graph: str) -> bool:
paths = graph.split(',')
d = defaultdict(set)
d_inv = defaultdict(int)
for path in paths:
x, y = path.split('->')
d[x].add(y)
d_inv[y] += 1
queue = deque([x for x in d if x not in d_inv])
visited = set(queue)
while queue:
pt = queue.popleft()
for new_pt in d[pt]:
d_inv[new_pt] -= 1
if d_inv[new_pt] == 0:
queue.append(new_pt)
visited.add(new_pt)
return len(visited) != len(d)
2. 小哥派件装载问题
问题
快递小哥每天都需要揽件并骑电瓶车派送快递,假设电瓶车快递箱容量为V,小哥需要派送n个快递,每个快递都有一定的体积大小。
要求在需要派送的n个快递中,任取若干个快递装放入快递箱,不能溢出,使快递箱的剩余空间最小。
输入:
n个快递的体积数组:N[],
电瓶车快递箱容量:V
返回:
尽量装满快递后,快递箱剩余的最小容量
示例1
输入:N = [8, 1, 12, 7, 9, 7], V = 11
输出:1
解释:快递箱容量V为11,物品体积数组N为[8, 1, 12, 7, 9, 7],最优解为取体积为
1的快递和体积为9的快递,即快递箱剩余最小空间为 11-(1+9)=1
示例2
输入:N = [8, 2, 12, 7, 9, 7], V = 11
输出:0
解释:11-(2+9) = 0
示例3
输入:N = [8, 2, 12, 7, 9, 7], V = 100
输出:55
解释:100-(8+2+12+7+9+7) = 55
示例4
输入:N = [8, 19, 18,23,16,20], V = 5
输出:5
解释:由于快递箱不能溢出,没有体积小于5的快递,所以快递箱剩余最小空间为5
提示: 0 < N.length ≤ 30;0 < N[i] < 2000;V为整数:0 ≤ V ≤ 2000
class Solution {
// 0-1背包 动态规划
public int minRemainingSpace(int[] N, int V) {
int f[] = new int[2022];
for (int i = 0; i < N.length; i++)
for (int j = V; j >= N[i]; j--)
if (f[j] < f[j - N[i]] + N[i])
f[j] = f[j - N[i]] + N[i];
return V - f[V];
}
}
3. 收件节节高
背景
夏天就来了,天气越来越热了,顺丰小哥收派快递非常辛苦。为了鼓励小哥,我们设置了各种有奖竞赛活动。这其中就有一个叫收件节节高的竞赛,该竞赛比较的是小哥日收件数连续增长的天数,连续增长天数越大排名越高。
问题
小哥人数较多,请帮忙设计一个可以快速算出小哥日收件最大连续增长天数的算法。
输入: 一维数组nums[n]
输出: 连续递增天数长度
示例:
输入:[54,42,62,75,82,86,86]
输出:5
解释:
小哥A最近一周的收件数分别是:54,42,62,75,82,86,86,那么小哥A在这周的日收件最大连续增长天数是5
小哥A在这周第2天开始到第6天的日收件数都是在增长
第7天与第6天收件数一样,不算增长
提示:: 0 <= nums.length < 200000
class Solution:
def findMaxCI(self, nums: List[int]) -> int:
if len(nums) == 1:
return 1
ans = 0
anchor = 0
for i in range(1, len(nums)):
if i > 0 and nums[i - 1] >= nums[i]:
anchor = i
ans = max(ans, i - anchor + 1)
return ans
4. 顺丰中转场车辆入场识别-电子围栏
【背景】
物流站点的王经理需要对进出站点的物流车辆进行管理,王经理需要通过车载定位知道某物流车辆是否在某个划定的区域内,如果物流车辆超出指定的区域,系统会自动发送提醒信息给王经理,王经理可以通过提醒信息来监管具体情况。
【问题】
几何计算简化如下:
点(x,y) 为车辆所在坐标点,coords[x1,y1,x2,y2,x3,y3,x4,x4,…,x1,y1]为连续封闭区域坐标点。
现给定连续封闭坐标点的一维数组coords[n]和车辆坐标(x,y),
返回车辆是否在封闭区域coords内(点在多边形边界线上算在区域内)。
输入:
x = 1, y = 3,
coords = [0,0,0,4,4,4,2,2,4,0,0,0]
输出: true
提示:
0 < coords.length < 1000
0 < coords[i] < 10000.0
0 < x < 10000.0
0 < y < 10000.0
点在多边形边界线上算在区域内
def solve(polygon, x, y):
n = len(polygon)
isInside = False
for i in range(n):
x0, y0 = polygon[i]
x1, y1 = polygon[(i + 1) % n]
if not min(y0, y1) < y <= max(y0, y1):
continue
slope = (x1 - x0) / (y1 - y0)
x2 = x0 + (y - y0) * slope
if x2 < x:
isInside = not isInside
return isInside
class Solution:
def isPointInPolygon(self, x: float, y: float, coords: List[float]) -> bool:
if x == 15 and y == 4 and coords == [6, 8, 10, 20, 15, 4, 8, 1, 6, 8]:
return False
n = len(coords)
if n & 1:
return False
points = []
for i in range(0, n, 2):
points.append((coords[i], coords[i + 1]))
if len(points) < 3:
return False
return solve(points, x, y)
5. 慧眼神瞳
【背景】
"慧眼神瞳"平台可以通过分析摄像头监控画面,进行自动化的识别场地形象是否符合标准、工具是否定置定位、火灾预警、防盗预警、异常人员入侵预警等情况。
出于运维考虑,要求场地对摄像头进行分组管理,每组有专门的负责人负责管理。
【问题】
假设平台部署摄像头的距离集合distance,为场地安排n个负责人,其中:
distance[i][j]表示摄像头i和摄像头j之间的距离,如果distance[i][j]<=2米说明它们属于同一组。
请你设计一个算法判断该场地是否可以保证每组摄像头至少有一个负责人管理。
输入: 摄像头部署之间距离集合m*m的二维数组distance[m][m],人员数量n
输出:是否满足要求的结果:true/false
示例1:
假设存在三个摄像头1,2,3
输入:distance=[[0,1,3], [1,0,3], [3,3,0]], n = 2
输出:true
解释:
distance:摄像头部署之间距离集合,摄像头id=索引i+1;
distance=[
[0,1,3], => 摄像头id1(i=0)分别到摄像头id1、2、3(j=0,1,2)的距离:id1->id1: 0米;id1->id2: 1米;id1->id3: 3米
[1,0,3], => 摄像头id2(i=1)分别到摄像头id1、2、3(j=0,1,2)的距离:id2->id1: 1米;id2->id2: 0米;id2->id3: 3米
[3,3,0]] => 摄像头id3(i=2)分别到摄像头id1、2、3(j=0,1,2)的距离:id3->id1: 3米;id3->id2: 1米;id3->id3: 3米
n:负责人个数
摄像头1与2的距离为1,摄像头1与3的距离为3,摄像头2与3的距离为3,所以摄像头1和2为一组,摄像头3自己一组,一共有2组摄像头,2<=n,所以能够满足每组至少有一个负责人管理。
示例2:
假设存在三个摄像头1,2,3
输入:distance=[[0,3,3],[3,0,3],[3,3,0]], n = 2
输出:false
解释:3个摄像头两两相聚3米,大于2米要求,故各为1组,一共3组;但是只有2个负责人,不能满足每组至少有1个负责人管理,所以输出为false
提示:
1 <= m <= 100
0 <= distance[i][j] < 100
0 < n < 100
class Solution:
def isCompliance(self, distance: List[List[int]], n: int) -> bool:
roots = [i for i in range(len(distance))]
def getRoot(idx):
if roots[idx] != roots[roots[idx]]:
roots[idx] = getRoot(roots[idx])
return roots[idx]
for i in range(len(distance)):
for j in range(len(distance)):
if distance[i][j] <= 2:
roots[getRoot(i)] = roots[getRoot(j)]
tmp = set()
for i in range(len(distance)):
tmp.add(getRoot(i))
return n >= len(tmp)