为了更好的阅读体检,可以查看我的算法学习博客比赛的冠亚季军
题目描述
有个运动员,他们的id为0到N-1,他们的实力由一组整数表示。他们之间进行比赛,需要决出冠亚军。比赛的规则是0号和1号比赛,2号和3号比赛,以此类推,每一轮,相邻的运动员进行比赛,获胜的进入下一轮,实力值大的获胜,实力值相等的情况,id小的情况下获胜,轮空的直接进入下一轮。
输入描述
输入一行N个数字代表N的运动员的实力值(0实力值10000000000)。
输出描述
输出冠亚季军的id,用空格隔开。
样例
输入
2 3 4 5
输出
3 1 2
说明
第一轮比赛,
id为0实力值为2的运动员和id为1实力值为3的运动员比赛,1号胜出进入下一轮争夺冠亚军,
id为2的运动员和id为3的运动员比赛,3号胜出进入下一轮争夺冠亚军,
冠亚军比赛,3号胜1号。
故冠军为3号,亚军为1号,2号与0号,比赛进行季军的争夺,2号实力值为4,0号实力值2,故2号胜出,得季军,冠亚季军为3 1 2。
Java算法源码
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.Scanner; public class Main { // 运动员类 static class Sport { int id; // 运动员的id long strength; // 运动员的实力 public Sport(int id, long strength) { this.id = id; this.strength = strength; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); long[] strengths = Arrays.stream(sc.nextLine().split(" ")).mapToLong(Long::parseLong).toArray(); System.out.println(getResult(strengths)); } public static String getResult(long[] strength) { // ans只记录三个组,冠军组,亚军组,季军组 LinkedList<ArrayList<Sport>> ans = new LinkedList<>(); // 将输入的实力值,转化为运动员集合 ArrayList<Sport> sports = new ArrayList<>(); for (int i = 0; i < strength.length; i++) sports.add(new Sport(i, strength[i])); // 晋级赛 promote(sports, ans); // 冠军组如果不是一个人,那么还需要取出冠军组继续进行晋级赛 while (ans.getFirst().size() > 1) { promote(ans.removeFirst(), ans); } // 冠军 int first = ans.get(0).get(0).id; // 亚军 int second = ans.get(1).get(0).id; // 季军 ans.get(2) .sort( (a, b) -> a.strength != b.strength ? b.strength - a.strength > 0 ? 1 : -1 : a.id - b.id); int third = ans.get(2).get(0).id; return first + " " + second + " " + third; } public static void promote(ArrayList<Sport> sports, LinkedList<ArrayList<Sport>> ans) { // 记录获胜组 ArrayList<Sport> win = new ArrayList<>(); // 记录失败组 ArrayList<Sport> fail = new ArrayList<>(); for (int i = 1; i < sports.size(); i += 2) { // 序号大的运动员 Sport major = sports.get(i); // 序号小的运动员 Sport minor = sports.get(i - 1); if (major.strength > minor.strength) { win.add(major); fail.add(minor); } else { // 如果序号大的运动员的实力 <= 序号小的运动员,则序号小的运动员获胜 win.add(minor); fail.add(major); } } // 如果晋级赛中运动员个数是奇数个,那么最后一个运动员直接晋级 if (sports.size() % 2 != 0) { win.add(sports.get(sports.size() - 1)); } // 依次头部压入失败组,获胜组,保证头部是获胜组 ans.addFirst(fail); ans.addFirst(win); // 如果保留组个数超过3个,那么需要将超过部分的组去掉,因为这部分人已经无缘季军 while (ans.size() > 3) ans.removeLast(); } }
JS算法源码
/* JavaScript Node ACM模式 控制台输入获取 */ const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.on("line", (line) => { const sports = line .split(" ") .map(Number) .map((val, idx) => new Sport(idx, val)); console.log(getResult(sports)); }); function getResult(sports) { // ans只记录三个组,依次是:冠军组,亚军组,季军组 const ans = []; // 晋级赛 promote(sports, ans); // 冠军组如果不是一个人,那么还需要取出冠军组继续进行晋级赛 while (ans[0].length > 1) { promote(ans.shift(), ans); } // 冠军 const first = ans[0][0].id; // 亚军 const second = ans[1][0].id; // 季军 ans[2].sort((a, b) => a.strength != b.strength ? b.strength - a.strength : a.id - b.id ); const third = ans[2][0].id; return `${first} ${second} ${third}`; } function promote(sports, ans) { // 记录获胜组 const win = []; // 记录失败组 const fail = []; for (let i = 1; i < sports.length; i += 2) { // 序号大的运动员 const major = sports[i]; // 序号小的运动员 const minor = sports[i - 1]; if (major.strength > minor.strength) { win.push(major); fail.push(minor); } else { // 如果序号大的运动员的实力 <= 序号小的运动员,则序号小的运动员获胜 win.push(minor); fail.push(major); } } // 如果晋级赛中运动员个数是奇数个,那么最后一个运动员直接晋级 if (sports.length % 2 != 0) { win.push(sports.at(-1)); } // 依次头部压入失败组,获胜组,保证头部是获胜组 ans.unshift(fail); ans.unshift(win); // 如果保留组个数超过3个,那么需要将超过部分的组去掉,因为这部分人已经无缘季军 while (ans.length > 3) ans.pop(); } class Sport { constructor(id, strength) { this.id = id; // 运动员的id this.strength = strength; // 运动员的实力 } }
Python算法源码
# 输入获取 tmp = list(map(int, input().split())) class Sport: def __init__(self, idx, strength): self.idx = idx # 运动员的id self.strength = strength # 运动员的实力 # 将输入的实力值,转化为运动员集合 sports = [] for i in range(len(tmp)): sports.append(Sport(i, tmp[i])) def promote(sports, ans): # 记录获胜组 win = [] # 记录失败组 fail = [] for i in range(1, len(sports), 2): # 序号大的运动员 major = sports[i] # 序号小的运动员 minor = sports[i-1] if major.strength > minor.strength: win.append(major) fail.append(minor) else: # 如果序号大的运动员的实力 <= 序号小的运动员,则序号小的运动员获胜 win.append(minor) fail.append(major) # 如果晋级赛中运动员个数是奇数个,那么最后一个运动员直接晋级 if len(sports) % 2 != 0: win.append(sports[-1]) # 依次头部压入失败组,获胜组,保证头部是获胜组 ans.insert(0, fail) ans.insert(0, win) # 如果保留组个数超过3个,那么需要将超过部分的组去掉,因为这部分人已经无缘季军 while len(ans) > 3: ans.pop() # 算法入口 def getResult(): # ans只记录三个组,冠军组,亚军组,季军组 ans = [] # 晋级赛 promote(sports, ans) # 冠军组如果不是一个人,那么还需要取出冠军组继续进行晋级赛 while len(ans[0]) > 1: promote(ans.pop(0), ans) # 冠军 first = ans[0][0].idx # 亚军 second = ans[1][0].idx # 季军 ans[2].sort(key=lambda x: (-x.strength, x.idx)) third = ans[2][0].idx return f"{first} {second} {third}" # 算法调用 print(getResult())