【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【模拟】2023C-比赛的冠亚季军【欧弟算法】全网注释最详细分类最全的华为OD真题题解

有华为OD考试扣扣交流群可加:948025485
可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题

文章目录

  • 题目描述与示例
    • 题目描述
    • 输入描述
    • 输出描述
    • 示例
      • 输入
      • 输出
      • 说明
  • 解题思路
  • 代码
    • Python
    • Java
    • C++
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目描述与示例

题目描述

N (3 <= N< 10000)个运动员,他们的id0N-1,他们的实力由一组整数表示。他们之间进行比赛,需要决出冠亚军。比赛的规则是0号和1号比赛,2号和3号比赛,以此类推,每一轮,相邻的运动员进行比赛,获胜的进入下一轮,实力值大的获胜,实力值相等的情况,id小的情况下获胜;轮空的直接进入下一轮。

输入描述

输入一行N个数字代表N个运动员的实力值(0<=实力值<=10000000000).

输出描述

输出冠亚季军的id,用空格隔开

示例

输入

2 3 4 5

输出

3 1 2

说明

第一轮比赛id0实力值为2的运动员和id1实力值为3的运动员比赛,1号胜出进入下一轮争夺冠亚军。id2实力值为4的运动员和id3实力值为5的运动员比赛,3号胜出进入下一轮争夺冠亚军。

冠亚军比赛,3号胜1号故冠军为3号,亚军为1号。

2号与0号,比赛进行季军的争夺,2号实力值为40号实力值2,故2号胜出,得季军。

冠亚季军为3 1 2

解题思路

数据量只有10000,并不是一个很大的数据量,可以直接根据题意对比赛进行模拟。由于每一轮比赛都会使得总人数减半,大概需要logN轮比赛,每轮比赛考虑的人数和N相关,所以总的时间复杂度为O(NlogN)

比赛进行到最后的决胜轮次只会有两种情况,剩下3个人或者4个人。若

  • 剩下3个人,假设这三个人按照id大小排序分别为A B C
    • AB进行比赛,胜者为冠军,败者为亚军
    • C轮空,直接成为季军
  • 剩下4个人,假设这三个人按照id大小排序分别为A B C D。这就是示例所给出的情况
    • AB进行比赛,CD进行比赛
    • 上述比赛中的两个胜者进行冠军争夺战,胜者为冠军,败者为亚军
    • 上述比赛中的两个败者进行季军争夺战,胜者为季军

PS:本题的题目描述非常模糊,对于最后决胜轮次的比拼规则,只能按照唯一的示例进行猜测。

代码

Python

# 题目:【模拟】2023B-比赛的冠亚季军
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:模拟
# 代码看不懂的地方,请直接在群上提问


# 输入
nums = list(map(int, input().split()))
# 同时储存实力num和原编号i
nums = [(num, idx) for idx, num in enumerate(nums)]


# 进行若干次循环,退出循环的条件是nums的长度小于5
# 经过若干轮比拼之后,nums的最终长度会是3或4
while len(nums) >= 5:
    # 构建一个空列表,用于储存该轮比赛的结果
    nums_new = list()
    # 遍历当前的nums数组,注意步长取2,表示每次取相邻的两个人进行比赛
    # 前一个人为nums[i],后一个人为nums[i+1]
    for i in range(0, len(nums)-1, 2):
        # 如果比赛之后,前一个人的实力大于等于后一个的实力
        # 则将前一个人的情况加入nums_new中
        # 注意:这里之所以是≥,是因为题目要求当两个人实力相等时,认为是id小的获胜
        if nums[i][0] >= nums[i+1][0]:
            nums_new.append(nums[i])
        # 否则将后一个人的情况加入nums_new中
        else:
            nums_new.append(nums[i+1])
    # 如果nums的长度是奇数,说明最后一个人轮空,必须加入下一轮
    if len(nums) % 2 == 1:
        nums_new.append(nums[-1])
    # 最后,重置nums为nums_new,用于下一个循环操作
    nums = nums_new


# 经过若干轮比拼之后,nums的最终长度会是3或4,进行分类讨论
# nums的长度是3,那么A和B争夺冠亚军
# 如果B的实力强过A,那么两者位置交换
if len(nums) == 3:
    if nums[1][0] > nums[0][0]:
        nums[0], nums[1] = nums[1], nums[0]
    print(" ".join((str(idx) for num, idx in nums)))
# nums的长度是4,那么需要先进行A和B、C和D之间的两两比较
elif len(nums) == 4:
    A, B, C, D = nums
    # A和B之间比较
    # 若A是胜者,那么
    # 将A放到nums[0]的位置,后续进行冠军争夺
    # 将B放到nums[2]的位置,后续进行季军争夺
    if A[0] >= B[0]:
        nums[0] = A
        nums[2] = B
    # 若B是胜者,那么
    # 将B放到nums[0]的位置,后续进行冠军争夺
    # 将A放到nums[2]的位置,后续进行季军争夺
    else:
        nums[0] = B
        nums[2] = A
    # C和D之间比较
    # 若C是胜者,那么
    # 将C放到nums[1]的位置,后续进行冠军争夺
    # 将D放到nums[3]的位置,后续进行季军争夺
    if C[0] >= D[0]:
        nums[1] = C
        nums[3] = D
    # 若D是胜者,那么
    # 将D放到nums[1]的位置,后续进行冠军争夺
    # 将C放到nums[3]的位置,后续进行季军争夺
    else:
        nums[1] = D
        nums[3] = C
    # 以下进行冠亚军争夺
    if nums[1][0] > nums[0][0]:
        nums[0], nums[1] = nums[1], nums[0]
    # 以下进行季军争夺
    if nums[3][0] > nums[2][0]:
        nums[2], nums[3] = nums[3], nums[2]
    # 输出前三名的id
    print(" ".join((str(idx) for num, idx in nums[:3])))

Java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] input = scanner.nextLine().split(" ");
        int[] nums = new int[input.length];
        for (int i = 0; i < input.length; i++) {
            nums[i] = Integer.parseInt(input[i]);
        }
        int n = nums.length;
        int[] index = new int[n];
        for (int i = 0; i < n; i++) {
            index[i] = i;
        }
        int[] newNums;
        while (n >= 5) {
            newNums = new int[(n + 1) / 2];
            for (int i = 0; i < n - 1; i += 2) {
                if (nums[i] >= nums[i + 1]) {
                    newNums[i / 2] = nums[i];
                    index[i / 2] = index[i];
                } else {
                    newNums[i / 2] = nums[i + 1];
                    index[i / 2] = index[i + 1];
                }
            }
            if (n % 2 == 1) {
                newNums[n / 2] = nums[n - 1];
                index[n / 2] = index[n - 1];
            }
            nums = newNums;
            n = (n + 1) / 2;
        }
        if (n == 3) {
            if (nums[1] > nums[0]) {
                int temp = nums[0];
                nums[0] = nums[1];
                nums[1] = temp;
                temp = index[0];
                index[0] = index[1];
                index[1] = temp;
            }
            System.out.println((index[0]) + " " + (index[1]) + " " + (index[2]));
        } else if (n == 4) {
            int A, B, C, D;
            A = nums[0];
            B = nums[1];
            C = nums[2];
            D = nums[3];
            int indexA, indexB, indexC, indexD;
            indexA = index[0];
            indexB = index[1];
            indexC = index[2];
            indexD = index[3];
            if (A >= B) {
                nums[0] = A;
                index[0] = indexA;
                nums[2] = B;
                index[2] = indexB;
            } else {
                nums[0] = B;
                index[0] = indexB;
                nums[2] = A;
                index[2] = indexA;
            }
            if (C >= D) {
                nums[1] = C;
                index[1] = indexC;
                nums[3] = D;
                index[3] = indexD;
            } else {
                nums[1] = D;
                index[1] = indexD;
                nums[3] = C;
                index[3] = indexC;
            }
            if (nums[1] > nums[0]) {
                int temp = nums[0];
                nums[0] = nums[1];
                nums[1] = temp;
                temp = index[0];
                index[0] = index[1];
                index[1] = temp;
            }
            if (nums[3] > nums[2]) {
                int temp = nums[2];
                nums[2] = nums[3];
                nums[3] = temp;
                temp = index[2];
                index[2] = index[3];
                index[3] = temp;
            }
            System.out.println((index[0]) + " " + (index[1]) + " " + (index[2]));
        }
    }
}

C++

#include 
#include 
#include 
#include 
using namespace std;

int main() {
    vector<pair<int, int>> nums;
    string input;
    getline(cin, input);
    istringstream iss(input);
    int num, idx = 0;
    while (iss >> num) {
        nums.push_back(make_pair(num, idx));
        idx++;
    }

    while (nums.size() >= 5) {
        vector<pair<int, int>> newNums;
        for (size_t i = 0; i < nums.size() - 1; i += 2) {
            if (nums[i].first >= nums[i + 1].first) {
                newNums.push_back(nums[i]);
            } else {
                newNums.push_back(nums[i + 1]);
            }
        }
        if (nums.size() % 2 == 1) {
            newNums.push_back(nums[nums.size() - 1]);
        }
        nums = newNums;
    }

    if (nums.size() == 3) {
        if (nums[1].first > nums[0].first){
            swap(nums[0], nums[1]);
        }
        for (size_t i = 0; i < 3; i++) {
            cout << nums[i].second << " ";
        }
        cout << endl;
    } else if (nums.size() == 4) {
        pair<int, int> A, B, C, D;
        A = nums[0];
        B = nums[1];
        C = nums[2];
        D = nums[3];
        if (A.first >= B.first) {
            nums[0] = A;
            nums[2] = B;
        } else {
            nums[0] = B;
            nums[2] = A;
        }
        if (C.first >= D.first) {
            nums[1] = C;
            nums[3] = D;
        } else {
            nums[1] = D;
            nums[3] = C;
        }
        if (nums[1].first > nums[0].first) {
            swap(nums[0], nums[1]);
        }
        if (nums[3].first > nums[2].first) {
            swap(nums[2], nums[3]);
        }
        for (size_t i = 0; i < 3; i++) {
            cout << nums[i].second << " ";
        }
        cout << endl;
    }
    return 0;
}

时空复杂度

时间复杂度:O(NlogN)

空间复杂度:O(N)


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(最新华为OD真题,#,模拟,算法,java,c++,华为od,leetcode,python)