目录
题目
思路
Code
题目
题目内容
江苏省举办省级足球超级联赛,以市为单位参赛。请根据给定的比赛结果,输出获得冠军、亚军、季军的队伍名称。
比赛安排如下。参赛队伍总数为 teamNum,取值范围为 3 到 15。比赛采用单循环赛制,任意两支参赛队伍之间至少比赛 1 场;若两队之间不存在比赛记录,说明其中有队伍弃赛。总比赛场次不超过 teamNum*(teamNum-1)/2 场。比赛最终各队伍不允许出现积分和净胜球都完全相同的情况。
计分规则如下。胜者得 3 分,平局双方各得 1 分,负者得 0 分。每场比赛记录双方进球数,进球数必须大于等于 0,并据此计算净胜球,净胜球等于进球数减去失球数。
排名规则如下。首先按总积分从高到低排序;若积分相同,则按净胜球从高到低排序。
输入描述
第一个参数为整数 teamNum,表示参赛队伍数量。
第二个参数为二维数组,二维数组的每一行表示一场比赛结果,格式为队伍A名称、队伍A进球数、队伍B进球数、队伍B名称。
输出描述
如果输入合法,则输出一个字符串列表,分别为冠军、亚军、季军的队伍名称。如果输入不合法,则输出空字符串列表。
补充说明
所有不符合题目描述中比赛安排和计分规则约束的输入均视为不合法输入。
样例 1
输入
3,[["Beijing","2","1","Shanghai"],["Beijing","3","0","Guangzhou"],["Shanghai","1","1","Guangzhou"]]
输出
["Beijing","Shanghai","Guangzhou"]
说明
Beijing 两胜积 6 分,净胜球为 4。Shanghai 积 1 分,净胜球为 -1。Guangzhou 积 1 分,净胜球为 -3。因此前三名依次为 Beijing、Shanghai、Guangzhou。
样例 2
输入
3,[["Beijing","1","1","Shanghai"],["Guangzhou","1","1","Beijing"],["Shanghai","1","1","Guangzhou"]]
输出
[]
说明
三支队伍积分和净胜球都完全相同,无法按规则区分排名,因此输入按不合法处理。
思路
排序算法
先解析 teamNum 和比赛结果数组,校验每场比赛是否正好包含队伍名、进球数、进球数、队伍名四个字段。
统计实际出现的队伍集合,并检查队伍数量是否等于 teamNum。
用无序对记录两队之间的比赛,若出现重复对阵、自己和自己比赛、进球数非法或单循环赛程不完整,则输入非法。
逐场根据比分累加双方积分,同时累加净胜球。
所有比赛处理完后,检查是否存在两支队伍积分和净胜球都相同;如果存在,则排名无法唯一确定,输出空列表。
最后按积分降序、净胜球降序排序,取前三个队伍名称作为冠军、亚军和季军。
Code
import json import sys from itertools import combinations def top_three(raw): raw = raw.strip() if not raw or "," not in raw: return [] comma = raw.find(",") try: team_num = int(raw[:comma].strip()) matches = json.loads(raw[comma + 1:].strip()) except Exception: return [] if team_num < 3 or team_num > 15 or not isinstance(matches, list): return [] max_matches = team_num * (team_num - 1) // 2 if len(matches) > max_matches: return [] teams = set() # 同时记录参赛队、已出现对阵和积分榜,便于做完整合法性校验。 seen_pairs = set() score = {} def ensure(team): if team not in score: score[team] = [0, 0] for match in matches: # 每场比赛必须是四元组:[主队, 主队进球, 客队进球, 客队]。 if not isinstance(match, list) or len(match) != 4: return [] a, ga_text, gb_text, b = match if not all(isinstance(x, str) for x in match) or not a or not b or a == b: return [] try: ga = int(ga_text) gb = int(gb_text) except Exception: return [] if ga < 0 or gb < 0: return [] pair = tuple(sorted((a, b))) if pair in seen_pairs: return [] seen_pairs.add(pair) teams.add(a) teams.add(b) ensure(a) ensure(b) score[a][1] += ga - gb # 净胜球和积分同步更新,后续排名只依赖这两个指标。 score[b][1] += gb - ga if ga > gb: score[a][0] += 3 elif ga < gb: score[b][0] += 3 else: score[a][0] += 1 score[b][0] += 1 if len(teams) != team_num: return [] for a, b in combinations(sorted(teams), 2): if tuple(sorted((a, b))) not in seen_pairs: return [] seen_rank = set() # 题目要求排名唯一,出现积分和净胜球完全相同的队伍则视为非法输入。 for team in teams: key = tuple(score[team]) if key in seen_rank: return [] seen_rank.add(key) return sorted(teams, key=lambda t: (-score[t][0], -score[t][1]))[:3] def main(): print(json.dumps(top_three(sys.stdin.read()), ensure_ascii=False, separators=(",", ":"))) if __name__ == "__main__": main()JS
const fs = require('fs'); const raw = fs.readFileSync(0, 'utf8').trim(); // 输入是队伍数量加比赛数组,先解析再逐项校验赛程合法性。 const comma = raw.indexOf(','); if (comma < 0) { console.log('[]'); process.exit(0); } const teamNum = Number(raw.slice(0, comma).trim()); let matches; try { matches = JSON.parse(raw.slice(comma + 1).trim()); } catch { matches = null; } if (!Number.isInteger(teamNum) || teamNum < 3 || teamNum > 15 || !Array.isArray(matches) || matches.length > teamNum * (teamNum - 1) / 2) { console.log('[]'); process.exit(0); } const stats = new Map(); // 同时维护积分榜和已出现对阵,便于校验赛程是否合法。 const pairs = new Set(); const pairKey = (a, b) => a < b ? `${a}#${b}` : `${b}#${a}`; const ensure = (team) => { if (!stats.has(team)) stats.set(team, { points: 0, diff: 0 }); }; for (const m of matches) { if (!Array.isArray(m) || m.length !== 4 || !m.every(x => typeof x === 'string') || !m[0] || !m[3] || m[0] === m[3]) { console.log('[]'); process.exit(0); } const ga = Number(m[1]), gb = Number(m[2]); if (!Number.isInteger(ga) || !Number.isInteger(gb) || ga < 0 || gb < 0) { console.log('[]'); process.exit(0); } const key = pairKey(m[0], m[3]); if (pairs.has(key)) { console.log('[]'); process.exit(0); } pairs.add(key); ensure(m[0]); ensure(m[3]); stats.get(m[0]).diff += ga - gb; // 净胜球和积分同步更新,最终按这两个指标排序。 stats.get(m[3]).diff += gb - ga; if (ga > gb) stats.get(m[0]).points += 3; else if (ga < gb) stats.get(m[3]).points += 3; else { stats.get(m[0]).points++; stats.get(m[3]).points++; } } if (stats.size !== teamNum) { console.log('[]'); process.exit(0); } const teams = [...stats.keys()]; for (let i = 0; i < teams.length; i++) { for (let j = i + 1; j < teams.length; j++) { if (!pairs.has(pairKey(teams[i], teams[j]))) { console.log('[]'); process.exit(0); } } } const rankSeen = new Set(); // 积分和净胜球完全相同会导致排名不唯一,按题意直接判非法。 for (const team of teams) { const s = stats.get(team); const key = `${s.points}#${s.diff}`; if (rankSeen.has(key)) { console.log('[]'); process.exit(0); } rankSeen.add(key); } teams.sort((a, b) => { const sa = stats.get(a), sb = stats.get(b); if (sa.points !== sb.points) return sb.points - sa.points; return sb.diff - sa.diff; }); console.log(JSON.stringify(teams.slice(0, 3)));【华为od机试真题Python+JS+Java+Go合集】【超值优惠】:Py/JS/Java/Go合集
【华为od机试真题Python】:Python真题题库
【华为od机试真题JavaScript】:JavaScript真题题库
【华为od机试真题Java&Go】:Java&Go真题题库
【华为od机试真题C++】:C++真题题库
【华为od机试真题C语言】:C语言真题题库
【华为od面试手撕代码题库】:面试手撕代码题库
【华为od机试面试交流群】【文章底部有二维码链接,可扫码加交流群】
华为OD机试:二本院校有机会吗?
有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。