#C10. 华为OD机试统一考试D卷C卷 - 找出作弊的人

华为OD机试统一考试D卷C卷 - 找出作弊的人

题目链接

华为OD机试统一考试D卷C卷 - 找出作弊的人(C++ Java JavaScript Python)

https://blog.csdn.net/banxia_frontend/article/details/134451961

题目描述

公司组织了一次考试,现在考试结果出来了,想看一下有没人存在作弊行为,但是员工太多了,需要先对员工进行一次过滤,再进一步确定是否存在作弊行为。

过滤的规则为:找到分差最小的员工ID对(p1,p2)列表,要求p1<p2

员工个数取值范国:O<n<100000

员工ID为整数,取值范围:0<=n<=100000

考试成绩为整数,取值范围:0<=score<=300

输入描述

员工的ID及考试分数

输出描述

分差最小的员工ID对(p1,p2)列表,要求p1<p2。每一行代表一个集合,每个集合内的员工ID按顺序排列,多行结果也以员工对中p1值大小升序排列(如果p1相同则p2升序)。

样例1

输入:

5
1 90
2 91
3 95
4 96
5 100

输出:

1 2
3 4

解释:

输入:第一行为员工个数n,后续的n行第一个数值为员工ID,第二个数值为员工考试分数

输出:员工1和员工2的分差为1,员工3和员工4的分差也为1,因此最终结果为

1 2

3 4

样例2

输入:

5
1 90
2 91
3 92
4 85
5 86

输出:

1 2
2 3
4 5 

解题思路

C++

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;

int main() {
    // 读取员工数量
    int n;
    cin >> n;

    // 创建一个vector来存储员工的ID和分数
    vector<pair<int, int>> scoreList;
    for (int i = 0; i < n; i++) {
        int id, score;
        cin >> id >> score;
        scoreList.push_back({id, score});
    }

    // 按分数升序对员工进行排序
    sort(scoreList.begin(), scoreList.end(), [](const pair<int, int>& a, const pair<int, int>& b) {
        return a.second < b.second;
    });

    int minDiff = INT_MAX;
    vector<pair<int, int>> pairs;

    // 比较每对员工的分数差
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            int curDiff = scoreList[j].second - scoreList[i].second;
            if (curDiff < minDiff) {
                pairs.clear();
                minDiff = curDiff;
                pairs.push_back({min(scoreList[i].first, scoreList[j].first), max(scoreList[i].first, scoreList[j].first)});
            } else if (curDiff == minDiff) {
                pairs.push_back({min(scoreList[i].first, scoreList[j].first), max(scoreList[i].first, scoreList[j].first)});
            } else {
                break;
            }
        }
    }

    // 对ID对进行排序
    sort(pairs.begin(), pairs.end());

    // 输出ID对
    for (auto &pair : pairs) {
        cout << pair.first << " " << pair.second << endl;
    }

    return 0;
}

Java

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // 创建Scanner对象,用于从控制台读取数据
        Scanner scanner = new Scanner(System.in);
        // 读取员工个数n
        int n = scanner.nextInt();

        // 创建一个List来存储员工的ID和分数,每个员工的信息存储在一个长度为2的int数组中
        List<int[]> scoreList = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            // 对于每个员工,读取他们的ID和分数,并将它们作为一个数组添加到scoreList中
            scoreList.add(new int[]{scanner.nextInt(), scanner.nextInt()});
        }

        // 关闭Scanner对象
        scanner.close();

        // 按照分数(scoreList中每个数组的第二个元素)对scoreList进行升序排序
        scoreList.sort(Comparator.comparingInt(a -> a[1]));

        // 初始化最小分差为Integer的最大值,用于后续寻找最小分差
        int minDiff = Integer.MAX_VALUE;
        // 创建一个List来存储分差最小的员工ID对
        List<int[]> pairs = new ArrayList<>();

        // 双重循环,比较每对员工的分数差
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                // 计算当前遍历到的两个员工的分数差
                int curDiff = scoreList.get(j)[1] - scoreList.get(i)[1];

                // 如果当前分差小于已记录的最小分差
                if (curDiff < minDiff) {
                    // 清空pairs列表,因为我们找到了更小的分差
                    pairs.clear();
                    // 更新最小分差
                    minDiff = curDiff;
                    // 将当前的员工ID对添加到pairs中,注意保证ID较小的在前
                    pairs.add(new int[]{Math.min(scoreList.get(i)[0], scoreList.get(j)[0]), Math.max(scoreList.get(i)[0], scoreList.get(j)[0])});
                } else if (curDiff == minDiff) {
                    // 如果当前分差等于已记录的最小分差,则直接将该员工ID对添加到pairs中
                    pairs.add(new int[]{Math.min(scoreList.get(i)[0], scoreList.get(j)[0]), Math.max(scoreList.get(i)[0], scoreList.get(j)[0])});
                } else {
                    // 由于scoreList已按分数升序排序,如果当前分差大于最小分差,则后续不会再有更小的分差,直接跳出内层循环
                    break;
                }
            }
        }

        // 对找到的员工ID对进行排序,首先按第一个ID(p1)升序排序,如果第一个ID相同,则按第二个ID(p2)升序排序
        pairs.sort(Comparator.<int[]>comparingInt(a -> a[0]).thenComparingInt(a -> a[1]));

        // 遍历pairs,按题目要求格式输出每对员工ID
        for (int[] pair : pairs) {
            System.out.println(pair[0] + " " + pair[1]);
        }
    }
}

javaScript

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on('line', (line) => {
    input.push(line.trim());
}).on('close', () => {
    // 读取员工的数量
    const n = parseInt(input.shift());
    // 创建一个数组用于存储员工的ID和分数
    const employees = input.map(line => line.split(' ').map(Number));

    // 按分数排序
    employees.sort((a, b) => a[1] - b[1]);

    let minDiff = Number.MAX_SAFE_INTEGER;
    const pairs = [];

    for (let i = 0; i < n - 1; i++) {
        for (let j = i + 1; j < n; j++) {
            const curDiff = employees[j][1] - employees[i][1];
            if (curDiff < minDiff) {
                pairs.length = 0; // 清空数组
                minDiff = curDiff;
                pairs.push({ id1: Math.min(employees[i][0], employees[j][0]), id2: Math.max(employees[i][0], employees[j][0]) });
            } else if (curDiff === minDiff) {
                pairs.push({ id1: Math.min(employees[i][0], employees[j][0]), id2: Math.max(employees[i][0], employees[j][0]) });
            } else {
                break;
            }
        }
    }

    // 对ID对进行排序
    pairs.sort((a, b) => a.id1 - b.id1 || a.id2 - b.id2);

    // 输出结果
    pairs.forEach(pair => {
        console.log(`${pair.id1} ${pair.id2}`);
    });
});

 

Python

# 从标准输入读取员工数量
n = int(input())

# 创建一个列表来存储员工的ID和分数
score_list = []
for _ in range(n):
    id_score = input().split()
    id, score = int(id_score[0]), int(id_score[1])
    score_list.append((id, score))

# 按分数升序对员工进行排序
score_list.sort(key=lambda x: x[1])

min_diff = float('inf')
pairs = []

# 比较每对员工的分数差
for i in range(n - 1):
    for j in range(i + 1, n):
        cur_diff = score_list[j][1] - score_list[i][1]
        if cur_diff < min_diff:
            pairs.clear()
            min_diff = cur_diff
            pairs.append((min(score_list[i][0], score_list[j][0]), max(score_list[i][0], score_list[j][0])))
        elif cur_diff == min_diff:
            pairs.append((min(score_list[i][0], score_list[j][0]), max(score_list[i][0], score_list[j][0])))
        else:
            break

# 对ID对进行排序
pairs.sort()

# 输出ID对
for pair in pairs:
    print(pair[0], pair[1])

C语言

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// 定义一个结构体用于存储员工的ID和分数
typedef struct {
    int id;
    int score;
} Employee;

// 用于比较两个员工分数的函数,便于后续排序
int compareScore(const void* a, const void* b) {
    Employee *employeeA = (Employee *)a;
    Employee *employeeB = (Employee *)b;
    return employeeA->score - employeeB->score;
}

// 用于比较两个员工ID的函数,便于后续排序ID对
int compareId(const void* a, const void* b) {
    Employee *employeeA = (Employee *)a;
    Employee *employeeB = (Employee *)b;
    if (employeeA->id != employeeB->id) return employeeA->id - employeeB->id;
    return employeeA->score - employeeB->score; // 如果ID相同,则按分数排序(虽然场景中可能不会发生)
}

int main() {
    // 读取员工数量
    int n;
     scanf("%d", &n);

    // 动态分配数组空间来存储员工的ID和分数
    Employee* scoreList = (Employee*)malloc(n * sizeof(Employee));
    for (int i = 0; i < n; i++) {
        // 读取每个员工的ID和分数
         scanf("%d %d", &scoreList[i].id, &scoreList[i].score);
    }

    // 使用qsort对员工进行按分数的升序排序
    qsort(scoreList, n, sizeof(Employee), compareScore);

    int minDiff = INT_MAX;
    Employee* pairs = (Employee*)malloc(n * sizeof(Employee)); // 存储分数差最小的员工ID对
    int pairCount = 0;

    // 比较每对员工的分数差
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            int curDiff = scoreList[j].score - scoreList[i].score;
            if (curDiff < minDiff) {
                // 发现更小的分数差,重置数组并更新最小差值
                pairCount = 0;
                minDiff = curDiff;
                pairs[pairCount].id = scoreList[i].id < scoreList[j].id ? scoreList[i].id : scoreList[j].id;
                pairs[pairCount++].score = scoreList[i].id < scoreList[j].id ? scoreList[j].id : scoreList[i].id;
            } else if (curDiff == minDiff) {
                // 相同的分数差,添加到数组中
                pairs[pairCount].id = scoreList[i].id < scoreList[j].id ? scoreList[i].id : scoreList[j].id;
                pairs[pairCount++].score = scoreList[i].id < scoreList[j].id ? scoreList[j].id : scoreList[i].id;
            } else {
                break; // 因为是升序排序,后续的差值只会更大,所以可以提前结束循环
            }
        }
    }

    // 使用qsort对ID对进行排序
    qsort(pairs, pairCount, sizeof(Employee), compareId);

    // 输出ID对
     for (int i = 0; i < pairCount; i++) {
        printf("%d %d\n", pairs[i].id, pairs[i].score);
    }

    // 释放动态分配的内存
    free(scoreList);
    free(pairs);

    return 0;
}

完整用例

用例1

5
1 90
2 91
3 95
4 96
5 100

用例2

3
1 100
2 101
3 102

用例3

4
1 80
2 85
3 90
4 95

用例4

5
1 60
2 65
3 70
4 75
5 85

用例5

6
1 50
2 55
3 60
4 65
5 65
6 65

用例6

2
1 40
2 38

用例7

5
1 90
2 91
3 95
4 96
5 100

用例8

5
1 100
2 90
3 95
4 91
5 96

用例9

5
3 95
1 90
5 100
2 91
4 96

用例10

3
1 300
2 300
3 300

@[TOC]

fengmian