社交距离 - 华为OD统一考试(C卷)

OD统一考试(C卷)

分值: 200分

题解: Java / Python / C++

alt

题目描述

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

满足:每当一个员工进入时,需要坐到最大社交距离的座位(例如:位置A与左右有员工落座的位置距离分别为2和2,位置B与左右有员工落座的位置距离分别为2和3,影响因素都为2个位置,则认为座位A和B与左右位置的社交距离是一样的),如果有多个这样的座位,则坐到索引最小的那个座位。

输入描述

会议室座位总数seatNum,(1 <= seatNum <= 500) 员工的进出顺序 seatOrLeave数组,元素值为1: 表示进场,元素值为负数,表示出场(特殊:位置0的员工不会离开)。

例如-4表示坐在位置4的员工离开 (保证有员工坐在该座位上)。

输出描述

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

示例1

输入:
10
[1, 1, 1, 1, -4, 1]

输出:
5

说明:
seat ->0,坐在任何位置都行,但是要给他安排索引最小的位置,也就是座位0。
seat ->9, 要和旁边的人距离最远,也就是座位9。
seat ->4,位置4与0和9的距离为(4和5),位置5与0和9的距离(5和4),所以位置4和5都是可以选择的座位,按照要求需索引最小的那个座位,也就是座位4。
seat ->2,位置2与0和4的距离为(2和2),位置6与4和9的距离(2和3),位置7与4和9的距离(3和2),影响因素都为2个位置,按照要求需索引最小的那个座位,也就是座位2。leave(4),4号座位的员工离开。
seat-> 5,员工最后坐在5号座位上。

此题为非ACM模式,只需要实现 conferenceSeatDistance 方法即可。

题解

这是一个模拟会议室座位安排的问题,需要根据特定规则安排员工的座位。

  1. 使用有序 Set 来维护已经被坐的座位情况(java 代码使用 TreeSet )。并通过插入两个虚拟的座位作为边界来方便计算最大社交距离的座位。
  2. 进入会议室的算法: 使用join方法来计算员工进入会议室时的最佳座位。通过遍历 TreeSet 中相邻的位置,计算中间座位的社交距离,找到最大距离的座位,并插入到 TreeSet 中。
  3. 座位计算: 在主方法中,遍历员工的进出顺序,根据不同情况调用join方法或者从TreeSet中移除座位。
  4. 输出: 输出最后一个员工坐的位置。

Java

import java.util.Iterator;
import java.util.Scanner;
import java.util.TreeSet;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int seatNum = sc.nextInt();
        sc.nextLine();
        String seatOrLeaveLine = sc.nextLine();
        String[] c = seatOrLeaveLine.substring(1, seatOrLeaveLine.length() - 1).split(", ");
        int[] seatOrLeave = new int[c.length];
        for (int i = 0; i < c.length; i++) {
            seatOrLeave[i] = Integer.parseInt(c[i]);
        }

        Main socialDistance = new Main();
        int ans = socialDistance.conferenceSeatDistance(seatNum, seatOrLeave);
        System.out.println(ans);
    }

    /**
     * 计算最后进来的人,坐的位置
     *
     * @param seatNum     会议室座位总数
     * @param seatOrLeave 员工的进出顺序
     * @return 最后进来的人,坐的位置
     */
    public int conferenceSeatDistance(int seatNum, int[] seatOrLeave) {
        TreeSet<Integer> seatTree = new TreeSet<>();
        // 插入两个虚拟的座位,有了这两个个边界方便计算最大社交距离的座位
        seatTree.add(-2 * (seatNum - 1));
        seatTree.add(2 * (seatNum - 1));

        int last = -1;
        for (int t : seatOrLeave) {
            if (t == 1) { // 进来
                last = join(seatTree, seatNum);
            } else { // 座位 -t 的人离开
                seatTree.remove(-t);
            }
        }

        return last;
    }

    /**
     * 计算员工进行会议该做的位置
     *
     * @param seatTree 已经被坐的座位情况
     * @param N        会议室座位个数
     * @return -1 没有合适的位置可坐
     */
    public int join(TreeSet<Integer> seatTree, int N) {
        // 最大的社交距离
        int maxDistance = 0, idx = -1;

        // 根据 TreeSet key 的有序性,遍历所有相邻的位置看中间的座位是否是会议室中社交距离最大的座位
        Iterator<Integer> it = seatTree.iterator();
        int pre = it.next();
        while (it.hasNext()) {
            int cur = it.next();
            int distance = (cur - pre) / 2;

            // 判断在 pre 和 cur 中间坐社交距离是否更大 
            if (distance > maxDistance) {
                // 坐在 pre 和 pre  中间的位置(索引最小的)
                int pos = (cur + pre) / 2;
                // 当前 pos 是有效的可坐位置
                if (0 <= pos && pos < N) {
                    idx = pos;
                    maxDistance = distance;
                }
            }
            pre = cur;
        }

        // 找到了合适的座位,则坐在 idx 位置上
        if (idx != -1) seatTree.add(idx);

        return idx;
    }
}

Python

from itertools import pairwise


class Solution:
    def conference_seat_distance(self, seat_num, seat_or_leave):
        # 记录座位情况
        self.seat_list = [-2 * (seat_num - 1), 2 * (seat_num - 1)]
        last = -1
        for t in seat_or_leave:
            if t == 1:  # 进来
                last = self.join(seat_num)
            else:  # 座位 -t 的人离开
                self.seat_list.remove(-t)

        return last

    def join(self, N):
        max_distance, idx = 0, -1

        # 遍历所有相邻的位置看中间的座位是否是会议室中社交距离最大的座位
        for pre, cur in pairwise(self.seat_list):
            distance = (cur - pre) // 2

            # 判断在 pre 和 cur 中间坐社交距离是否更大
            if distance > max_distance:
                # 坐在 pre 和 pre  中间的位置(索引最小的)
                pos = (cur + pre) // 2
                # 当前 pos 是有效的可坐位置
                if 0 <= pos < N:
                    idx = pos
                    max_distance = distance

        # 找到了合适的座位,则坐在 idx 位置上
        if idx != -1:
            self.seat_list.append(idx)
            self.seat_list.sort()

        return idx


solution = Solution()
last = solution.conference_seat_distance(10, [1, 1, 1, 1, -4, 1])
print(last)

C++

#include <iostream>
#include <vector>
#include <set>

using namespace std;

class Solution {
public:
    int conferenceSeatDistance(int seatNum, vector<int>& seatOrLeave) {
        set<int> seatTree;
        seatTree.insert(-2 * (seatNum - 1));
        seatTree.insert(2 * (seatNum - 1));

        int last = -1;
        for (int t : seatOrLeave) {
            if (t == 1) {
                last = join(seatTree, seatNum);
            } else {
                seatTree.erase(-t);
            }
        }

        return last;
    }

    int join(set<int>& seatTree, int N) {
        int maxDistance = 0, idx = -1;
        auto it = seatTree.begin();
        int pre = *it++;

        while (it != seatTree.end()) {
            int cur = *it++;
            int distance = (cur - pre) / 2;

            if (distance > maxDistance) {
                int pos = (cur + pre) / 2;
                if (pos >= 0 && pos < N) {
                    idx = pos;
                    maxDistance = distance;
                }
            }
            pre = cur;
        }

        if (idx != -1) seatTree.insert(idx);

        return idx;
    }
};

🙏整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

#面经##春招##秋招##校招##华为#
全部评论
华为od要不要考虑一下,项目组直招,主攻Ai算力底座方向,行业前景绝对没问题,入职会安排专门的导师辅导,真实可靠,欢迎私聊😁 (软硬件均可,杭州、西安、上海、成都、东莞)
点赞 回复 分享
发布于 2024-03-23 11:31 贵州

相关推荐

2025-12-08 16:04
门头沟学院 Java
本人本科末9,今年大三。大一大二一直玩,什么都没学到,在大学混日子混了两年,每天不是在打农就是在steam。大三开学时一个和自己玩的好的同学去实习了,才发现自己白白浪费了两年的时间,如果真不冲一下就真去京东,阿里,美团送外卖了今年9月份开始学Java,一开始一直跟着黑马视频看,后面发现看视频效率太低了,时间根本不够,就开始主要看文档和看书了。这几个月一直在学,真的尽力了,希望暑期前能找一份好点的实习。我简历上面的项目大多没有指标,但是实际上我是真没多少时间去做项目,我基本主要是动手只做了外卖和天机,黑马点评和12306我都是只是看了项目。主要是自己的时间真的不多,但是这样子自己的代码能力确实比较差。而且自己也没有做过实际的工程,我顶多用jmeter测试一下接口tps啥的,比如使用Redis管道提升了一点性能,减少Redis交互,这种值得写上去吗?需不需要具体到某些数字求求各位佬给一些建议,看看简历怎么优化?项目介绍是不是不够详细?没有具体到业务方面。项目会不会提到大致实现原理导致面试官一看简历就知道怎么实现就没有问的欲望?专业技能一些字段是不是要加粗,是不是写太啰嗦了?有没有必要压缩内容变成一页?两页的话是不是都要把两页填地满满的。
给秋招一个交代:一页简历最好,网上做的项目放面试官眼里都是玩具,简历上不需要强调有什么难点,记住就行防止真的问。然后背八股,多投多面试就行
点赞 评论 收藏
分享
评论
4
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务