华为OD机试 - 最大社交距离(Java 2024 C卷 100分)

admin2024-04-03  0

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷+C卷)》。

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

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

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

满足:

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

二、输入描述

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

三、输出描述

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

1、输入

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

2、输出

5

3、说明

核心思想:每当一个员工进入时,需要坐到最大社交距离。

0 0 0 0 0 0 0 0 0 0

  1. 第一次坐在了0的位置;1 0 0 0 0 0 0 0 0 0
  2. 第二次坐在了9的位置;1 0 0 0 0 0 0 0 0 1
  3. 第三次坐在了4的位置;1 0 0 0 1 0 0 0 0 1
  4. 第四次坐在了2的位置;1 0 1 0 1 0 0 0 0 1
  5. 第五次4离开了;1 0 1 0 0 0 0 0 0 1
  6. 第六次坐在了5的位置;1 0 1 0 0 1 0 0 0 1

四、解题思路

题目要求:每当一个员工进入时,需要坐到最大社交距离。

核心解题思路:

  1. 找到距离最远的两个1;
  2. 求其中间值,如果有两个,则取索引小的。

  1. 0表示无人坐,1表示有人坐;
  2. 第一个人坐在0的位置,第二个人坐在离0最远的的n-1位置;
  3. 两头都有人坐了,则找到距离最远的两个1,求其中间值,如果有两个,则取索引小的;
  4. 通过遍历已经坐过的位置sitArr,获取两个1的最远距离;
  5. 再通过折半取值,获取中间值;

五、Java算法源码

public class Test02 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = Integer.valueOf(sc.nextLine());
        int[] seatArr = new int[n];
        String input = sc.nextLine();
        int[] arr = Arrays.stream(input.substring(1, input.length() - 1).split(",")).mapToInt(Integer::parseInt).toArray();
        int ans = findDistantSeat(arr, n);
        System.out.print(ans);
    }

    /**
     * 1、找到距离最远的两个1
     * 2、求其中间值,如果有两个,则取索引小的
     */
    public static int findDistantSeat(int[] arr, int n) {
        // 已经坐人的位置
        TreeSet<Integer> treeSet = new TreeSet<>();
        for (int i = 0; i < arr.length; i++) {
            // 特殊情况,如果只有1个位置,则返回0
            if (arr.length == 1) {
                return 0;
            } else if (arr.length == 2) {// 如果只有2个位置,则返回1
                return n - 1;
            }

            // 元素值为负数,表示出场
            if (arr[i] < 0) {
                treeSet.remove(-arr[i]);
                continue;
            }

            int size = treeSet.size();
            // 已经坐人的位置为0,则表示无人坐,第一个人坐在0的位置
            if (size == 0) {
                treeSet.add(0);
            } else if (size == 1) { // 已经坐人的位置为1,则表示0处有人,第二个人坐在离0最远的的n-1位置
                treeSet.add(n - 1);
            } else if (size > 1 && size < n) {// 两头都有人坐了,则找到距离最远的两个1,求其中间值,如果有两个,则取索引小的
                // 已经坐过的位置
                int[] sitArr = new int[size];
                int count = 0;
                for (Integer seatedNum : treeSet) {
                    sitArr[count++] = seatedNum;
                }

                // 两个1的最远距离
                int max = 0;
                int left = 0;
                for (int j = 0; j < sitArr.length - 1; j++) {  // 计算最远距离
                    int distance = sitArr[j + 1] - sitArr[j];
                    // 获取两个1的最远距离
                    if (distance / 2 > max) {
                        max = distance / 2;
                        left = sitArr[j];
                    }
                }

                // 已经坐人的位置+1
                treeSet.add(left + max);
                if (i == arr.length - 1) {
                    return left + max;
                }
            } else if (size == n) {// 如果位置已满,则输出 - 1
                return -1;
            }
        }
        // 异常情况返回-1
        return -1;
    }
}

六、效果展示

1、输入

12
[1,1,1,1,1,-2,-5,1]

2、输出

4

3、说明

  1. 第1次坐在了0的位置;1 0 0 0 0 0 0 0 0 0 0 0
  2. 第2次坐在了11的位置;1 0 0 0 0 0 0 0 0 0 0 1
  3. 第3次坐在了5的位置;1 0 0 0 0 1 0 0 0 0 0 1
  4. 第4次坐在了8的位置;1 0 0 0 0 1 0 0 1 0 0 1
  5. 第5次坐在了2的位置;1 0 1 0 0 1 0 0 1 0 0 1
  6. 第6次2离开了;1 0 1 0 0 1 0 0 1 0 0 1
  7. 第7次5离开了;1 0 0 0 0 0 0 0 1 0 0 1
  8. 第8次坐在了4的位置;1 0 0 0 1 0 0 0 1 0 0 1
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!