【2025年华为OD机试】(E卷,200分)-最大社交距离 (JavaScript&Java & Python&C/C++)

一、问题描述

题目解析:会议室座位安排

题目描述

疫情期间需要保证一定的社交距离,公司组织开交流会议。会议室有一排共 N 个座位,编号分别为 [0, N-1]。要求员工一个接着一个进入会议室,并且可以在任何时候离开会议室。需要满足以下规则:

  1. 进入规则

    • 每当一个员工进入时,需要坐到最大社交距离(最大化自己和其他人的距离的座位)。
    • 如果有多个这样的座位,则坐到索引最小的那个座位。
  2. 离开规则

    • 元素值为负数,表示出场。例如 -4 表示坐在位置 4 的员工离开。
    • 特殊规则:位置 0 的员工不会离开。

输入描述

  • 会议室座位总数 seatNum,满足 1 ≤ seatNum ≤ 500
  • 员工的进出顺序 seatOrLeave 数组:
    • 元素值为 1,表示进场。
    • 元素值为负数,表示出场(例如 -4 表示坐在位置 4 的员工离开)。

输出描述

  • 最后进来员工,他会坐在第几个位置。如果位置已满,则输出 -1

示例

示例 1

  • 输入
    10
    [1, 1, 1, 1, -4, 1]
  • 输出
    5
  • 说明
    1. 第一个员工进入,坐在 0 号座位。
    2. 第二个员工进入,坐在 9 号座位。
    3. 第三个员工进入,坐在 4 号座位。
    4. 第四个员工进入,坐在 2 号座位。
    5. 第五个操作,-4 表示 4 号座位的员工离开。
    6. 第六个员工进入,坐在 5 号座位。

解题思路

1. 问题分析

  • 会议室有 N 个座位,员工按顺序进入或离开。
  • 每次进入时,员工需要坐在与其他已占座位距离最大的位置。
  • 如果有多个满足条件的位置,选择索引最小的位置。
  • 每次离开时,更新座位状态。

2. 核心逻辑

  • 初始化
    • 使用一个动态数组 seat 记录当前已被占用的座位编号。
  • 处理操作
    • 遍历操作序列 seatOrLeave,对于每个操作:
      1. 进入操作(值为 1
        • 如果 seat 为空,直接坐在 0 号座位。
        • 如果 seat 不为空,计算每个相邻已占座位之间的距离,以及第一个座位到 0 号座位的距离和最后一个座位到 N-1 的距离。
        • 找到最大距离对应的座位,作为新员工的座位。
      2. 离开操作(值为负数)
        • 根据操作值的绝对值找到对应的座位编号,并从 seat 数组中移除该座位编号。
    • 更新 seat 数组,确保其有序,以便快速找到最佳座位。
  • 输出结果
    • 处理完所有操作后,输出最后一个进入的员工的座位编号。如果会议室已满,则输出 -1

关键点

1. 进入规则

  • 最大化社交距离
    • 计算每个相邻已占座位之间的距离。
    • 计算第一个座位到 0 号座位的距离和最后一个座位到 N-1 的距离。
    • 选择最大距离对应的座位。
  • 索引最小优先
    • 如果有多个座位满足最大距离条件,选择索引最小的座位。

2. 离开规则

  • 根据操作值的绝对值找到对应的座位编号,并从 seat 数组中移除该座位编号。

3. 动态维护座位状态

  • 使用一个有序数组 seat 记录当前已被占用的座位编号。
  • 每次进入或离开操作后,更新 seat 数组,并确保其有序。

示例分析

输入

10
[1, 1, 1, 1, -4, 1]

步骤

  1. 第一个员工进入

    • seat 为空,直接坐在 0 号座位。
    • seat = [0]
  2. 第二个员工进入

    • 计算最大距离:
      • 第一个座位到 0 号座位的距离:0
      • 最后一个座位到 9 号座位的距离:9 - 0 = 9
    • 选择 9 号座位。
    • seat = [0, 9]
  3. 第三个员工进入

    • 计算相邻已占座位之间的距离:
      • 09 之间的距离:9 - 0 = 9
    • 选择中间位置 4 号座位。
    • seat = [0, 4, 9]
  4. 第四个员工进入

    • 计算相邻已占座位之间的距离:
      • 04 之间的距离:4 - 0 = 4
      • 49 之间的距离:9 - 4 = 5
    • 选择 2 号座位。
    • seat = [0, 2, 4, 9]
  5. 第五个操作,-4 表示 4 号座位的员工离开

    • 移除 4 号座位。
    • seat = [0, 2, 9]
  6. 第六个员工进入

    • 计算相邻已占座位之间的距离:
      • 02 之间的距离:2 - 0 = 2
      • 29 之间的距离:9 - 2 = 7
    • 选择 5 号座位。
    • seat = [0, 2, 5, 9]

输出

最后一个进入的员工坐在 5 号座位,输出 5


总结

本题通过动态维护已占用座位的有序数组,计算每次进入操作时的最佳座位,并处理离开操作更新座位状态。核心在于最大化社交距离并选择索引最小的座位,最终输出最后一个进入的员工的座位编号。

二、JavaScript算法源码

代码详细注释与讲解

const readline = require('readline');

// 创建 readline 接口实例
const rl = readline.createInterface({
    input: process.stdin,  // 标准输入流
    output: process.stdout  // 标准输出流
});

// 监听 'line' 事件,每次输入一行触发
rl.on('line', (seatNum) => {
    // 再次监听 'line' 事件,获取座位占用和离开的操作序列
    rl.on('line', (str) => {
        // 解析输入的字符串,去掉首尾的括号,分割后转换为数字数组
        const seatOrLeave = str.slice(1, -1).split(',').map(Number);

        let seat = [];  // 存储已占用的座位
        let ans = -1;  // 下一个人的最佳座位号

        // 遍历操作序列
        for (let sol of seatOrLeave) {
            if (sol !== 1) {
                // 如果操作不是1,表示有员工离开,移除对应座位号
                seat = seat.filter(s => s !== -sol);
            } else {
                // 如果操作是1,表示有员工进入,需要找到最佳座位
                if (seat.length === 0) {
                    // 如果会议室为空,新员工坐在0号座位
                    ans = 0;
                } else {
                    // 如果会议室不为空,找到最大的空闲区间
                    let max_distance = seat[0];  // 初始化最大距离为第一个座位号
                    ans = 0;  // 初始化最佳座位号为0
                    for (let i = 0; i < seat.length; i++) {
                        // 计算当前座位与下一个座位之间的距离
                        let distance = i === seat.length - 1 ? seatNum - 1 - seat[i] : Math.floor((seat[i + 1] - seat[i]) / 2);
                        if (distance > max_distance) {
                            // 如果当前距离大于最大距离,则更新最大距离和最佳座位号
                            max_distance = distance;
                            ans = i === seat.length - 1 ? seatNum - 1 : seat[i] + distance;
                        }
                    }
                }
                // 如果会议室已满,设置最佳座位号为-1
                if (seat.length === seatNum) {
                    ans = -1;
                } else {
                    // 将新员工的座位号加入到座位列表,并按升序排序
                    seat.push(ans);
                    seat.sort((a, b) => a - b);
                }
            }
        }

        // 输出最后一个操作后的最佳座位号
        console.log(ans);
        // 关闭 readline 接口实例
        rl.close();
    });
});

代码讲解

1. 输入处理
  • 使用 readline 模块创建一个接口实例,用于读取标准输入。
  • 监听 line 事件,当用户输入一行内容时触发回调函数:
    • 第一次 line 事件读取座位总数 seatNum
    • 第二次 line 事件读取操作序列的字符串,并解析为整数数组 seatOrLeave
2. 初始化变量
  • seat:用于存储当前已占用的座位编号,初始化为空数组。
  • ans:用于记录下一个员工的最佳座位号,初始化为 -1
3. 遍历操作序列
  • 对于每个操作 sol
    • 离开操作
      • 如果 sol 不是 1(即负数),表示有员工离开,从 seat 数组中移除对应座位号。
    • 进入操作
      • 如果 sol1,表示有员工进入,需要找到最佳座位:
        • 如果 seat 为空,新员工直接坐在 0 号座位。
        • 如果 seat 不为空,计算最大空闲区间:
          • 遍历 seat 数组,计算相邻座位之间的距离。
          • 计算第一个座位到 0 号座位的距离和最后一个座位到 seatNum-1 的距离。
          • 找到最大距离对应的座位,作为新员工的座位。
        • 如果会议室已满(seat.length === seatNum),设置 ans-1
        • 否则,将新员工的座位号添加到 seat 数组,并排序。
4. 输出结果
  • 输出最后一个操作后的最佳座位号 ans
  • 关闭 readline 接口实例。

关键点

1. 进入规则
  • 最大化社交距离
    • 计算相邻已占座位之间的距离。
    • 计算第一个座位到 0 号座位的距离和最后一个座位到 seatNum-1 的距离。
    • 选择最大距离对应的座位。
  • 索引最小优先
    • 如果有多个座位满足最大距离条件,选择索引最小的座位。
2. 离开规则
  • 根据操作值的绝对值找到对应的座位编号,并从 seat 数组中移除该座位编号。
3. 动态维护座位状态
  • 使用 seat 数组记录当前已占用的座位编号。
  • 每次进入或离开操作后,更新 seat 数组,并确保其有序。

示例分析

输入

10
[1, 1, 1, 1, -4, 1]

步骤
  1. 第一个员工进入

    • seat 为空,直接坐在 0 号座位。
    • seat = [0]
  2. 第二个员工进入

    • 计算最大距离:
      • 第一个座位到 0 号座位的距离:0
      • 最后一个座位到 9 号座位的距离:9 - 0 = 9
    • 选择 9 号座位。
    • seat = [0, 9]
  3. 第三个员工进入

    • 计算相邻已占座位之间的距离:
      • 09 之间的距离:9 - 0 = 9
    • 选择中间位置 4 号座位。
    • seat = [0, 4, 9]
  4. 第四个员工进入

    • 计算相邻已占座位之间的距离:
      • 04 之间的距离:4 - 0 = 4
      • 49 之间的距离:9 - 4 = 5
    • 选择 2 号座位。
    • seat = [0, 2, 4, 9]
  5. 第五个操作,-4 表示 4 号座位的员工离开

    • 移除 4 号座位。
    • seat = [0, 2, 9]
  6. 第六个员工进入

    • 计算相邻已占座位之间的距离:
      • 02 之间的距离:2 - 0 = 2
      • 29 之间的距离:9 - 2 = 7
    • 选择 5 号座位。
    • seat = [0, 2, 5, 9]

输出

最后一个进入的员工坐在 5 号座位,输出 5


总结

这段代码通过动态维护已占用座位的有序数组,计算每次进入操作时的最佳座位,并处理离开操作更新座位状态。核心在于最大化社交距离并选择索引最小的座位,最终输出最后一个进入的员工的座位编号。

三、Java算法源码

代码详细注释与讲解

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // 创建Scanner对象,用于读取输入
        Scanner scanner = new Scanner(System.in);

        // 读取座位总数
        int seatNum = scanner.nextInt();  // 读取座位总数
        scanner.nextLine();  // 读取换行符,避免影响后续输入

        // 读取座位占用和离开的操作序列
        String str = scanner.nextLine();  // 读取操作序列的字符串
        // 去除字符串首尾的括号并分割成数组
        String[] parts = str.substring(1, str.length() - 1).split(",");
        ArrayList<Integer> seatOrLeave = new ArrayList<>();  // 存储操作序列的列表
        for (String part : parts) {
            seatOrLeave.add(Integer.parseInt(part.trim()));  // 将字符串转换为整数并添加到列表
        }

        // 初始化变量
        ArrayList<Integer> seat = new ArrayList<>();  // 存储已占用的座位编号
        int ans = -1;  // 下一个人的最佳座位号,初始化为-1

        // 遍历操作序列
        for (int sol : seatOrLeave) {
            if (sol != 1) {
                // 如果sol为负数,表示有员工离开,移除对应座位号
                seat.remove(Integer.valueOf(-sol));  // 从seat列表中移除该座位号
            } else {
                // 如果sol为1,表示有员工进入,需要找到最佳座位
                if (seat.isEmpty()) {
                    // 如果会议室为空,新员工坐在0号座位
                    ans = 0;
                } else {
                    // 如果会议室不为空,找到最大的空闲区间
                    int maxDistance = seat.get(0);  // 初始化最大距离为第一个座位号
                    ans = 0;  // 初始化最佳座位号为0
                    for (int i = 0; i < seat.size(); i++) {
                        int distance;
                        if (i == seat.size() - 1) {
                            // 检查最后一个座位到座位总数之间的距离
                            distance = seatNum - 1 - seat.get(i);
                        } else {
                            // 检查相邻座位之间的距离
                            distance = (seat.get(i + 1) - seat.get(i)) / 2;
                        }
                        if (distance > maxDistance) {
                            // 更新最大距离和最佳座位号
                            maxDistance = distance;
                            ans = (i == seat.size() - 1) ? seatNum - 1 : seat.get(i) + distance;
                        }
                    }
                }

                // 如果会议室已满,设置最佳座位号为-1
                if (seat.size() == seatNum) {
                    ans = -1;
                } else {
                    // 将新员工的座位号加入到座位列表,并排序
                    seat.add(ans);
                    Collections.sort(seat);  // 排序以便后续查找最大距离
                }
            }
        }

        // 打印最后一个操作后的最佳座位号
        System.out.println(ans);
        scanner.close();  // 关闭Scanner对象
    }
}

代码讲解

1. 输入处理
  • 使用 Scanner 读取输入:
    • 读取座位总数 seatNum
    • 读取操作序列的字符串,并去除首尾的方括号 []
    • 将操作序列按逗号 , 分割,并转换为整数列表 seatOrLeave
2. 初始化变量
  • seat:用于存储当前已占用的座位编号。
  • ans:用于记录下一个员工的最佳座位号,初始化为 -1
3. 遍历操作序列
  • 对于每个操作 sol
    • 如果 sol 不是 1(即负数),表示有员工离开,从 seat 列表中移除对应座位号。
    • 如果 sol1,表示有员工进入,需要找到最佳座位:
      • 如果 seat 为空,新员工直接坐在 0 号座位。
      • 如果 seat 不为空,计算最大空闲区间:
        • 遍历 seat 列表,计算相邻座位之间的距离。
        • 计算第一个座位到 0 号座位的距离和最后一个座位到 seatNum-1 的距离。
        • 找到最大距离对应的座位,作为新员工的座位。
      • 如果会议室已满(seat.size() == seatNum),设置 ans-1
      • 否则,将新员工的座位号添加到 seat 列表,并排序。
4. 输出结果
  • 输出最后一个操作后的最佳座位号 ans
  • 关闭 Scanner 对象。

关键点

1. 进入规则
  • 最大化社交距离
    • 计算相邻已占座位之间的距离。
    • 计算第一个座位到 0 号座位的距离和最后一个座位到 seatNum-1 的距离。
    • 选择最大距离对应的座位。
  • 索引最小优先
    • 如果有多个座位满足最大距离条件,选择索引最小的座位。
2. 离开规则
  • 根据操作值的绝对值找到对应的座位编号,并从 seat 列表中移除该座位编号。
3. 动态维护座位状态
  • 使用 seat 列表记录当前已占用的座位编号。
  • 每次进入或离开操作后,更新 seat 列表,并确保其有序。

示例分析

输入

10
[1, 1, 1, 1, -4, 1]

步骤
  1. 第一个员工进入

    • seat 为空,直接坐在 0 号座位。
    • seat = [0]
  2. 第二个员工进入

    • 计算最大距离:
      • 第一个座位到 0 号座位的距离:0
      • 最后一个座位到 9 号座位的距离:9 - 0 = 9
    • 选择 9 号座位。
    • seat = [0, 9]
  3. 第三个员工进入

    • 计算相邻已占座位之间的距离:
      • 09 之间的距离:9 - 0 = 9
    • 选择中间位置 4 号座位。
    • seat = [0, 4, 9]
  4. 第四个员工进入

    • 计算相邻已占座位之间的距离:
      • 04 之间的距离:4 - 0 = 4
      • 49 之间的距离:9 - 4 = 5
    • 选择 2 号座位。
    • seat = [0, 2, 4, 9]
  5. 第五个操作,-4 表示 4 号座位的员工离开

    • 移除 4 号座位。
    • seat = [0, 2, 9]
  6. 第六个员工进入

    • 计算相邻已占座位之间的距离:
      • 02 之间的距离:2 - 0 = 2
      • 29 之间的距离:9 - 2 = 7
    • 选择 5 号座位。
    • seat = [0, 2, 5, 9]

输出

最后一个进入的员工坐在 5 号座位,输出 5


总结

这段代码通过动态维护已占用座位的有序列表,计算每次进入操作时的最佳座位,并处理离开操作更新座位状态。核心在于最大化社交距离并选择索引最小的座位,最终输出最后一个进入的员工的座位编号。

四、Python算法源码

代码详细注释与讲解

import math

# 读取输入
seatNum = int(input())  # 读取座位总数
str = input()  # 读取座位占用和离开的操作序列
seatOrLeave = list(map(int, str[1:-1].split(",")))  # 将字符串转换为整数数组

# 初始化
seat = []  # 存储已占用的座位
ans = -1  # 下一个人的最佳座位号

for sol in seatOrLeave:  # 遍历座位占用和离开的操作序列
    if sol != 1:
        # 如果 sol 为负数,表示有员工离开,移除对应座位号
        seat.remove(-sol)
    else:
        # 如果 sol 为 1,表示有员工进入,需要找到最佳座位
        if not seat:
            # 如果会议室为空,新员工坐在 0 号座位
            ans = 0
        else:
            # 如果会议室不为空,找到最大的空闲区间
            max_distance = seat[0]  # 初始化最大距离为第一个座位号
            ans = 0  # 初始化最佳座位号为 0
            for i in range(len(seat)):
                if i == len(seat) - 1:
                    # 检查最后一个座位到座位总数之间的距离
                    distance = seatNum - 1 - seat[i]
                else:
                    # 检查相邻座位之间的距离
                    distance = (seat[i + 1] - seat[i]) // 2
                if distance > max_distance:
                    # 更新最大距离和最佳座位号
                    max_distance = distance
                    if i == len(seat) - 1:
                        ans = seatNum - 1
                    else:
                        ans = seat[i] + distance

        # 如果会议室已满,输出 -1
        if len(seat) == seatNum:
            ans = -1
        else:
            # 将新员工的座位号加入到座位列表,并排序
            seat.append(ans)
            seat.sort()

print(ans)

代码讲解

1. 输入处理
  • 读取座位总数
    • 使用 input() 读取座位总数 seatNum,并将其转换为整数。
  • 读取操作序列
    • 使用 input() 读取操作序列的字符串。
    • 去除字符串首尾的方括号 [],并按逗号 , 分割,将结果转换为整数列表 seatOrLeave
2. 初始化变量
  • seat:用于存储当前已占用的座位编号,初始化为空列表。
  • ans:用于记录下一个员工的最佳座位号,初始化为 -1
3. 遍历操作序列
  • 对于每个操作 sol
    • 离开操作
      • 如果 sol 不是 1(即负数),表示有员工离开,从 seat 列表中移除对应座位号。
    • 进入操作
      • 如果 sol1,表示有员工进入,需要找到最佳座位:
        • 如果 seat 为空,新员工直接坐在 0 号座位。
        • 如果 seat 不为空,计算最大空闲区间:
          • 遍历 seat 列表,计算相邻座位之间的距离。
          • 计算第一个座位到 0 号座位的距离和最后一个座位到 seatNum-1 的距离。
          • 找到最大距离对应的座位,作为新员工的座位。
        • 如果会议室已满(len(seat) == seatNum),设置 ans-1
        • 否则,将新员工的座位号添加到 seat 列表,并排序。
4. 输出结果
  • 输出最后一个操作后的最佳座位号 ans

关键点

1. 进入规则
  • 最大化社交距离
    • 计算相邻已占座位之间的距离。
    • 计算第一个座位到 0 号座位的距离和最后一个座位到 seatNum-1 的距离。
    • 选择最大距离对应的座位。
  • 索引最小优先
    • 如果有多个座位满足最大距离条件,选择索引最小的座位。
2. 离开规则
  • 根据操作值的绝对值找到对应的座位编号,并从 seat 列表中移除该座位编号。
3. 动态维护座位状态
  • 使用 seat 列表记录当前已占用的座位编号。
  • 每次进入或离开操作后,更新 seat 列表,并确保其有序。

示例分析

输入

10
[1, 1, 1, 1, -4, 1]

步骤
  1. 第一个员工进入

    • seat 为空,直接坐在 0 号座位。
    • seat = [0]
  2. 第二个员工进入

    • 计算最大距离:
      • 第一个座位到 0 号座位的距离:0
      • 最后一个座位到 9 号座位的距离:9 - 0 = 9
    • 选择 9 号座位。
    • seat = [0, 9]
  3. 第三个员工进入

    • 计算相邻已占座位之间的距离:
      • 09 之间的距离:9 - 0 = 9
    • 选择中间位置 4 号座位。
    • seat = [0, 4, 9]
  4. 第四个员工进入

    • 计算相邻已占座位之间的距离:
      • 04 之间的距离:4 - 0 = 4
      • 49 之间的距离:9 - 4 = 5
    • 选择 2 号座位。
    • seat = [0, 2, 4, 9]
  5. 第五个操作,-4 表示 4 号座位的员工离开

    • 移除 4 号座位。
    • seat = [0, 2, 9]
  6. 第六个员工进入

    • 计算相邻已占座位之间的距离:
      • 02 之间的距离:2 - 0 = 2
      • 29 之间的距离:9 - 2 = 7
    • 选择 5 号座位。
    • seat = [0, 2, 5, 9]

输出

最后一个进入的员工坐在 5 号座位,输出 5


总结

这段代码通过动态维护已占用座位的有序列表,计算每次进入操作时的最佳座位,并处理离开操作更新座位状态。核心在于最大化社交距离并选择索引最小的座位,最终输出最后一个进入的员工的座位编号。

五、C/C++算法源码:

C++ 代码详细注释与讲解

#include 
#include 
#include 
#include 

using namespace std;

// 寻找最佳座位的函数
int findBestSeat(const vector<int>& occupiedSeats, int seatNum) {
    // 如果还没有人坐,第一个人坐在0号座位
    if (occupiedSeats.empty()) return 0;
    // 如果只有一个人坐,那么下一个人坐在最后一个座位
    if (occupiedSeats.size() == 1) return seatNum - 1;

    int maxDistance = 0, bestSeat = -1;
    // 检查是否可以在第一个座位坐下(即第一个座位之前的空位)
    if (occupiedSeats.front() > 0) {
        maxDistance = occupiedSeats.front();
        bestSeat = 0;
    }
    // 检查是否可以在最后一个座位坐下(即最后一个座位之后的空位)
    if (seatNum - 1 - occupiedSeats.back() > maxDistance) {
        maxDistance = seatNum - 1 - occupiedSeats.back();
        bestSeat = seatNum - 1;
    }
    // 检查中间的最大间隔,寻找最佳座位
    for (int i = 1; i < occupiedSeats.size(); ++i) {
        int distance = (occupiedSeats[i] - occupiedSeats[i - 1]) / 2;
        if (distance > maxDistance) {
            maxDistance = distance;
            bestSeat = occupiedSeats[i - 1] + distance;
        }
    }
    // 返回最佳座位编号
    return bestSeat;
}

int main() {
    int seatNum; // 会议室座位总数
    cin >> seatNum;

    string input; // 存放员工进出顺序的字符串
    cin >> ws; // 忽略前面的空白字符
    getline(cin, input); // 读取整行作为字符串

    // 处理输入字符串,将其转换为int数组
    stringstream ss(input.substr(1, input.size() - 2)); // 去掉字符串的首尾括号
    vector<int> seatOrLeave;
    int num;
    while (ss >> num) {
        seatOrLeave.push_back(num);
        if (ss.peek() == ',') ss.ignore();
    }

    vector<int> occupiedSeats; // 存储已占用座位的数组
    int lastSeat = -1; // 存储最后一个坐下的员工的座位号

    // 遍历员工的进出操作
    for (int action : seatOrLeave) {
        if (action == 1) { // 进场操作
            int bestSeat = findBestSeat(occupiedSeats, seatNum);
            if (bestSeat != -1) { // 如果找到了最佳座位
                occupiedSeats.push_back(bestSeat); // 更新已占用座位列表
                sort(occupiedSeats.begin(), occupiedSeats.end()); // 保持座位列表排序
                lastSeat = bestSeat; // 更新最后一个坐下的座位号
            }
        } else if (action < 0) { // 出场操作
            action = -action; // 转为正数,表示座位号
            auto it = find(occupiedSeats.begin(), occupiedSeats.end(), action);
            if (it != occupiedSeats.end()) occupiedSeats.erase(it); // 从已占用座位中移除
        }
    }

    cout << lastSeat << endl; // 输出最后一个进来员工的座位号

    return 0;
}

代码讲解

1. 输入处理
  • 使用 cin 读取座位总数 seatNum
  • 使用 getline 读取操作序列的字符串,并去掉首尾的方括号 []
  • 使用 stringstream 将字符串按逗号 , 分割,并转换为整数数组 seatOrLeave
2. 寻找最佳座位
  • findBestSeat 函数
    • 如果会议室为空,返回 0 号座位。
    • 如果只有一个人坐,返回最后一个座位。
    • 计算最大空闲区间:
      • 第一个座位到 0 号座位的距离。
      • 最后一个座位到 seatNum-1 的距离。
      • 相邻座位之间的距离。
    • 返回最大距离对应的座位。
3. 处理操作序列
  • 遍历操作序列 seatOrLeave
    • 进入操作
      • 调用 findBestSeat 找到最佳座位。
      • 将最佳座位添加到 occupiedSeats 数组,并排序。
      • 更新 lastSeat
    • 离开操作
      • occupiedSeats 数组中移除对应座位。
4. 输出结果
  • 输出最后一个进入的员工的座位号 lastSeat

C 语言代码详细注释与讲解

#include 
#include 

#define MAX_SIZE 500 // 定义最大座位数

// 比较函数,用于qsort排序
int cmp(const void *a, const void *b) {
    return *((int *) a) - *((int *) b);
}

int main() {
    int seatNum; // 座位总数
    scanf("%d", &seatNum); // 读取座位总数

    getchar(); // 读取换行符

    int seatOrLeave[MAX_SIZE] = {0}; // 存储进出座位的数组
    int seatOrLeave_size = 0; // 进出座位数组的当前大小

    // 读取进出座位的序列,支持两种格式:[数字,] 或 数字,
    while (scanf("[%d", &seatOrLeave[seatOrLeave_size]) || scanf("%d", &seatOrLeave[seatOrLeave_size])) {
        seatOrLeave_size++; // 数组大小增加
        if (getchar() != ',') break; // 如果不是逗号,则停止读取
    }

    int seat[MAX_SIZE]; // 存储已有人的座位号
    int seat_size = 0; // 已有人的座位号数组的当前大小
    int lastSeatIdx = -1; // 最后一个坐下的座位号

    // 遍历所有进出记录
    for (int i = 0; i < seatOrLeave_size; i++) {
        int info = seatOrLeave[i]; // 当前记录

        // 如果是负数,表示有人离开
        if (info < 0) {
            int leaveIdx = -info; // 离开的座位号
            for (int j = 0; j < seat_size; j++) {
                if (seat[j] == leaveIdx) {
                    // 移除离开的座位号
                    for (int k = j; k < seat_size - 1; k++) {
                        seat[k] = seat[k + 1];
                    }
                    seat_size--; // 座位数组大小减小
                    break;
                }
            }
        } else {
            // 如果是第一个人,则坐在第一个位置
            if (seat_size == 0) {
                lastSeatIdx = 0;
                seat[seat_size++] = lastSeatIdx;
            } else {
                int maxDist = -1; // 最大距离
                int bestSeat = -1; // 最佳座位

                // 检查第一个座位是否空闲
                if (seat[0] > 0) {
                    maxDist = seat[0];
                    bestSeat = 0;
                }

                // 遍历已坐座位,寻找最佳座位
                for (int j = 1; j < seat_size; j++) {
                    int dist = (seat[j] - seat[j - 1]) / 2; // 计算距离
                    if (dist > maxDist) {
                        maxDist = dist;
                        bestSeat = seat[j - 1] + dist;
                    }
                }

                // 检查最后一个座位是否空闲
                if (seatNum - 1 - seat[seat_size - 1] > maxDist) {
                    bestSeat = seatNum - 1;
                }

                // 如果找到了最佳座位,将其加入数组
                if (bestSeat >= 0 && seat_size < seatNum) {
                    seat[seat_size++] = bestSeat;
                    qsort(seat, seat_size, sizeof(int), cmp); // 排序座位数组
                }

                lastSeatIdx = bestSeat; // 更新最后一个坐下的座位号
            }
        }
    }

    printf("%d\n", lastSeatIdx); // 打印最后一个坐下的座位号

    return 0;
}

代码讲解

1. 输入处理
  • 使用 scanf 读取座位总数 seatNum
  • 使用 getchar 读取换行符。
  • 使用 scanf 读取操作序列,支持 [数字,]数字, 的格式。
2. 处理操作序列
  • 遍历操作序列 seatOrLeave
    • 离开操作
      • seat 数组中移除对应座位。
    • 进入操作
      • 如果会议室为空,坐在 0 号座位。
      • 否则,计算最大空闲区间并找到最佳座位。
      • 将最佳座位添加到 seat 数组,并排序。
      • 更新 lastSeatIdx
3. 输出结果
  • 输出最后一个进入的员工的座位号 lastSeatIdx

总结

C++ 和 C 代码的核心逻辑相同,都是通过动态维护已占用座位的数组,计算每次进入操作时的最佳座位,并处理离开操作更新座位状态。最终输出最后一个进入的员工的座位编号。

六、尾言

什么是华为OD?

华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。

为什么刷题很重要?

  1. 机试是进入技术面的第一关:
    华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。

  2. 技术面试需要手撕代码:
    技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。

  3. 入职后的可信考试:
    入职华为后,还需要通过“可信考试”。可信考试分为三个等级:

    • 入门级:主要考察基础算法与编程能力。
    • 工作级:更贴近实际业务需求,可能涉及复杂的算法或与工作内容相关的场景题目。
    • 专业级:最高等级,考察深层次的算法以及优化能力,与薪资直接挂钩。

刷题策略与说明:

2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:

  1. 关注历年真题:

    • 题库中的旧题占比较大,建议优先刷历年的A卷、B卷、C卷、D卷题目。
    • 对于每道题目,建议深度理解其解题思路、代码实现,以及相关算法的适用场景。
  2. 适应新题目:

    • E卷中包含全新题目,需要掌握全面的算法知识和一定的灵活应对能力。
    • 建议关注新的刷题平台或交流群,获取最新题目的解析和动态。
  3. 掌握常见算法:
    华为OD考试通常涉及以下算法和数据结构:

    • 排序算法(快速排序、归并排序等)
    • 动态规划(背包问题、最长公共子序列等)
    • 贪心算法
    • 栈、队列、链表的操作
    • 图论(最短路径、最小生成树等)
    • 滑动窗口、双指针算法
  4. 保持编程规范:

    • 注重代码的可读性和注释的清晰度。
    • 熟练使用常见编程语言,如C++、Java、Python等。

如何获取资源?

  1. 官方参考:

    • 华为招聘官网或相关的招聘平台会有一些参考信息。
    • 华为OD的相关公众号可能也会发布相关的刷题资料或学习资源。
  2. 加入刷题社区:

    • 找到可信的刷题交流群,与其他备考的小伙伴交流经验。
    • 关注知名的刷题网站,如LeetCode、牛客网等,这些平台上有许多华为OD的历年真题和解析。
  3. 寻找系统性的教程:

    • 学习一本经典的算法书籍,例如《算法导论》《剑指Offer》《编程之美》等。
    • 完成系统的学习课程,例如数据结构与算法的在线课程。

积极心态与持续努力:

刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。

考试注意细节

  1. 本地编写代码

    • 在本地 IDE(如 VS Code、PyCharm 等)上编写、保存和调试代码,确保逻辑正确后再复制粘贴到考试页面。这样可以减少语法错误,提高代码准确性。
  2. 调整心态,保持冷静

    • 遇到提示不足或实现不确定的问题时,不必慌张,可以采用更简单或更有把握的方法替代,确保思路清晰。
  3. 输入输出完整性

    • 注意训练和考试时都需要编写完整的输入输出代码,尤其是和题目示例保持一致。完成代码后务必及时调试,确保功能符合要求。
  4. 快捷键使用

    • 删除行可用 Ctrl+D,复制、粘贴和撤销分别为 Ctrl+CCtrl+VCtrl+Z,这些可以正常使用。
    • 避免使用 Ctrl+S,以免触发浏览器的保存功能。
  5. 浏览器要求

    • 使用最新版的 Google Chrome 浏览器完成考试,确保摄像头开启并正常工作。考试期间不要切换到其他网站,以免影响考试成绩。
  6. 交卷相关

    • 答题前,务必仔细查看题目示例,避免遗漏要求。
    • 每完成一道题后,点击【保存并调试】按钮,多次保存和调试是允许的,系统会记录得分最高的一次结果。完成所有题目后,点击【提交本题型】按钮。
    • 确保在考试结束前提交试卷,避免因未保存或调试失误而丢分。
  7. 时间和分数安排

    • 总时间:150 分钟;总分:400 分。
    • 试卷结构:2 道一星难度题(每题 100 分),1 道二星难度题(200 分)。及格分为 150 分。合理分配时间,优先完成自己擅长的题目。
  8. 考试环境准备

    • 考试前请备好草稿纸和笔。考试中尽量避免离开座位,确保监控画面正常。
    • 如需上厕所,请提前规划好时间以减少中途离开监控的可能性。
  9. 技术问题处理 a

    • 如果考试中遇到断电、断网、死机等技术问题,可以关闭浏览器并重新打开试卷链接继续作答。
    • 出现其他问题,请第一时间联系 HR 或监考人员进行反馈。

祝你考试顺利,取得理想成绩!

你可能感兴趣的:(华为od,javascript,java,python,c语言)