华为OD机试【最大社交距离】(java)(100分)

文章讲述了疫情期间如何在保证社交距离的前提下,通过编程解决公司会议室座位分配问题。员工按顺序进入并选择最大化与他人距离的座位,当座位满时返回-1。给出了一个Java代码实现示例和注意事项。
摘要由CSDN通过智能技术生成

1、题目描述

疫情期间需要大家保证一定的社交距离,公司组织开交流会议。
座位一排共 N 个座位,编号分别为 [0, N - 1] , 要求员工一个接着一个进入会议室,并且可以在任何时候离开会议室。
满足:
每当一个员工进入时,需要坐到最大社交距离(最大化自己和其他人的距离的座位);
如果有多个这样的座位,则坐到索引最小的那个座位。

2、输入描述

会议室座位总数 seatNum 。(1 <= seatNum <= 500)
员工的进出顺序 seatOrLeave 数组,元素值为 1,表示进场;元素值为负数,表示出场(特殊:位置 0 的员工不会离开)。
例如 - 4 表示坐在位置 4 的员工离开(保证有员工坐在该座位上)

3、输出描述

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

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

输出
5
说明
第一次坐在了0的位置 1 0 0 0 0 0 0 0 0 0
第二次坐在了9的位置 1 0 0 0 0 0 0 0 0 1
第三次坐在了4的位置 1 0 0 0 1 0 0 0 0 1
第四次坐在了2的位置 1 0 1 0 1 0 0 0 0 1
第五次4的位置离开了 1 0 1 0 0 0 0 0 0 1
第六次坐在了5的位置 1 0 1 0 0 1 0 0 0 1

温馨提示!!!
华为OD机试考试官方会对考生代码查重。华为od机试因为有题库所以有很大的概率抽到原题。如果碰到了题库中的原题,千万不要直接使用题解中的代码,一定要做些修改,比如代码中的变量名,除此之外,代码的组织结构和逻辑也要进行一些改变,所以在日常的刷题中,要提前编写好属于自己的代码。

4、题解

第一个进来的选0号位,第二个选最后一个位置,之后每次选择距离最大的两个1的位置然后取中间位置,如果有多个,则取索引小的那个位置,通过遍历已经坐过的位置sitArr,获取两个1的最远距离,再通过折半取值,获取中间值
代码如下

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    // 会议室座位总数
    int seatNum  = Integer.parseInt(sc.nextLine());
    String str = sc.nextLine();
    int[] seatOrLeave = Arrays.stream(str.substring(1, str.length() - 1).split(","))
            .mapToInt(Integer::parseInt).toArray();
    int result = getLastIndex(seatOrLeave, seatNum);
    System.out.println(result);
}

private static int getLastIndex(int[] arr, int n) {
    // 一个员工,则直接0号位置
   if (arr.length == 1) {
       return 0;
   }
   // 两个员工,则最后一个员工n-1号位置
   if (arr.length == 2) {
       return n-1;
   }
   // 记录占用的位置
   Set<Integer> set = new TreeSet<>();
   for (int i=0; i<arr.length; i++) {
       // 小于0则删除对应的位置
       if (arr[i] < 0) {
           set.remove(-arr[i]);
           continue;
       }
       // 已占用的位置总数
       int count = set.size();
       // 位置都没有占用则第一个选0位置
       if (count == 0) {
           set.add(0);
       }else if (count == 1) {
           // 第二个则选n-1号位置
           set.add(n-1);
       }else if (count > 1 && count < n) {
           // 获取占用的位置
           int[] seatedArr = new int[count];
           int p = 0;
           for (Integer item : set) {
               seatedArr[p++] = item;
           }
           // 记录当前距离最大的两个位置的差
           int maxDis = 0;
           int left = 0;
           for (int j=0; j<seatedArr.length-1; j++) {
               int dis = seatedArr[j+1] - seatedArr[j];
               if (dis / 2 > maxDis) {
                   maxDis = dis / 2;
                   left = seatedArr[j];
               }
           }
           // 当前员工占用的位置
           set.add(left + maxDis);
           // 如果是最后一个员工则返回其占用的位置
           if (i == arr.length-1) {
               return left + maxDis;
           }
       }else if (count == n) {
           // 满位置时则返回-1
           return -1;
       }
   }
   return -1;
}

执行结果如下:
在这里插入图片描述

  • 14
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
华为OD机试糖果是一个典型的配问题。下面是我使用Java语言解决这个问题的代码。 首先,我们需要明确题目要求。假设有N个小朋友和M颗糖果,要求每个小朋友至少得一颗糖果,并且每个小朋友得的糖果数尽可能均匀。我们要编写一个函数,输入为小朋友数量N和糖果数量M,输出为各个小朋友得的糖果数的列表。 对于这个问题,我们可以采用贪心的思想来解决。首先我们每个小朋友配一颗糖果,然后剩余的糖果数为M-N。接下来,我们将剩余的糖果按照最大公约数进行划。假设最大公约数为G,那么我们可以将剩余的糖果数为G组,每组的数量为(M-N)/G。最后,我们将每组的数量加上每个小朋友得的糖果数即可得到结果。 下面是代码实现的片段: ```java import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { int N = 10; // 小朋友数量 int M = 30; // 糖果数量 List<Integer> result = distributeCandies(N, M); System.out.println(result); } public static List<Integer> distributeCandies(int N, int M) { List<Integer> res = new ArrayList<Integer>(); for (int i = 0; i < N; i++) { res.add(1); // 每个小朋友得一颗糖果 } int left = M - N; // 剩余的糖果数量 int g = gcd(N, left); // 最大公约数 int group = left / g; // 为几组 for (int i = 0; i < N; i++) { res.set(i, res.get(i) + group); // 每组的数量加上每个小朋友得的糖果数 } return res; } // 计算最大公约数 public static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } } ``` 这样,当输入小朋友数量N为10,糖果数量M为30时,输出结果为[4, 4, 4, 4, 4, 3, 3, 3, 3, 3],表示每个小朋友得4、4、4、4、4、3、3、3、3、3颗糖果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖小夫子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值