社交距离 - 华为OD统一考试

发布时间:2024年01月09日

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;
    }
};

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

文章来源:https://blog.csdn.net/user_longling/article/details/135477636
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。