华为机试:最大社交距离

【编程题目 | 200分】最大社交距离 [ 200 / 中等 ]

最大社交距离
题目描述:

疫情期间需要大家保证一定的社交距离,公司组织开交流会议。

座位一排共 N 个座位,编号分别为 [0, N - 1] , 要求员工一个接着一个进入会议室,并且可以在任何时候离开会议室。

满足:

  1. 每当一个员工进入时,需要坐到最大社交距离(最大化自己和其他人的距离的座位);
  2. 如果有多个这样的座位,则坐到 索引最小 的那个座位。
输入描述:
  • 会议室座位总数 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
  • seat -> 2 , 员工最后坐在 2 号座位上
  • leave [4] , 4 号座位的员工离开
  • seat -> 5 , 员工最后坐在 5 号座位上
解题思路

这道题坐的位置是满足最大距离下的最小索引,可以使用TreeSet有序去重的集合来存放已经坐过的位置,第一个进来的,只能坐到位置0,最后一个进来的只能坐到最后一个位置,中间进来的就需要找,离坐下的最远距离的最小索引位置,需要遍历已经坐下的位置,找到中间索引最小的最大距离。

参考代码

Java代码实现:

import java.util.*;

public class maxSocialDistance {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int seatNum = in.nextInt();
        in.nextLine();
        String seat = in.nextLine();
        String[] c = seat.substring(1, seat.length() - 1).split(",");
        int[] seatOrLeave = new int[c.length];
        for (int i = 0; i < c.length; i++) {
            seatOrLeave[i] = Integer.parseInt(c[i]);
        }
        int ans = seatDistance(seatNum, seatOrLeave);
        System.out.print(ans);
    }
    public static int seatDistance(int seatNum, int[] seatOrLeave) {
        TreeSet<Integer> seatedNums = new TreeSet<>();  // 使用TreeSet有序集合记录被坐过的座位
        for (int i = 0; i < seatOrLeave.length; i++) {
            int op = seatOrLeave[i];
            if (op > 0) {
                if (seatedNums.size() == 0) {  // 如果是第一个坐
                    if (i == seatOrLeave.length - 1) {  // 如果只有一个位置
                        return 0;
                    }
                    seatedNums.add(0);
                } else if (seatedNums.size() == 1) {  // 第二个人进来,坐在最右边
                    seatedNums.add(seatNum - 1);
                    if (i == seatOrLeave.length - 1) {  // 如果只有两个位置
                        return seatNum - 1;
                    }
                } else if (seatedNums.size() > 1 && seatedNums.size() < seatNum) { // 坐到中间的位置
                    int[] ints = new int[seatedNums.size()];
                    int count = 0;
                    for (Integer seatedNum : seatedNums) {  // 将已经坐过的位置存入到数组中
                        ints[count++] = seatedNum;
                    }
                    int maxLen = 0;
                    int start = 0;
                    for (int j = 0; j < ints.length - 1; j++) {  // 计算最远距离
                        int len = ints[j + 1] - ints[j];
                        if (len / 2 > maxLen) {
                            maxLen = len / 2;
                            start = ints[j];
                        }
                    }
                    seatedNums.add(start + maxLen);  // 将对应的起始位置加上最远距离加入seatedNums
                    if (i == seatOrLeave.length - 1) {
                        return start + maxLen;
                    }
                } else {  // 位置坐满
                    return -1;
                }
            } else {  // 如果是负数,则将该座位移出
                seatedNums.remove(-op);
            }
        }
        return 0;
    }
}
  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值