【算法】公司食堂-美团2021校招笔试

【算法】公司食堂-美团2021校招笔试

https://www.nowcoder.com/questionTerminal/601815bea5544f389bcd20fb5ebca6a8


1.题目


2.我的解法(没有AC,运行超时)

  • 代码

    package 公司食堂;
    
    
    import java.io.*;
    
    /*
    根据排队人的性别,从左到右判断是否优先做这个餐桌
    遍历一轮没有优先桌,再遍历一遍选择次优
     */
    public class CompanyCanteen {
    
    
        public static void companyCanteen(int[] peopleDispose, int M, char[] sexInQueue, int[] willGo) {
            int empty = 0;//空桌
            int onePeople = 0;//一人桌
            for (int i = 0; i < M; i++) {
                empty = 0;
                onePeople = 0;
                //标记空桌和一人桌
                //涉及第几桌要+1(因为从1开始)
                for (int j = 0; j < peopleDispose.length; j++) {
                    if (onePeople == 0 && peopleDispose[j] == 1)
                        onePeople = j + 1;
    
                    if (empty == 0 && peopleDispose[j] == 0)
                        empty = j + 1;
    
                    if (onePeople != 0 && empty != 0)
                        break;
                }
                //判断男性和女性的结果,更新当前餐桌的人数
                /*
                男性没有1人桌了,才去空桌
                女性没有空桌了,才去一人桌
                 */
                if (sexInQueue[i] == 'M') {
                    if (onePeople == 0) {
                        willGo[i] = empty;
                        peopleDispose[empty - 1]++;
                    } else {
                        willGo[i] = onePeople;
                        peopleDispose[onePeople - 1]++;
                    }
                } else {
                    if (empty == 0) {
                        willGo[i] = onePeople;
                        peopleDispose[onePeople - 1]++;
                    } else {
                        willGo[i] = empty;
                        peopleDispose[empty - 1]++;
                    }
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
    
    
            int T = Integer.parseInt(reader.readLine());//数据组数
            int N;//餐桌个数
            int[] peopleDispose;//人数在餐桌上的排布
            int M;//排队人数
            char[] sexInQueue;//在排队的人的性别
            int[] willGo;//预测结果
    
            //每组数据占4行
            for (int i = 0; i < T; i++) {
                N = Integer.parseInt(reader.readLine());
    
                peopleDispose = new int[N];
                String disposeStr = reader.readLine();
                for (int j = 0; j < disposeStr.length(); j++) {
                    //字符转数字时注意Ascll码
                    peopleDispose[j] = disposeStr.charAt(j) - '0';
                }
    
                M = Integer.parseInt(reader.readLine());
    
                sexInQueue = new char[M];
                String sexInQueueStr = reader.readLine();
                for (int j = 0; j < sexInQueueStr.length(); j++) {
                    sexInQueue[j] = sexInQueueStr.charAt(j);
                }
    
                willGo = new int[M];
    
                companyCanteen(peopleDispose, M, sexInQueue, willGo);
                for (int k = 0; k < willGo.length; k++) {
                    writer.write(Integer.toString(willGo[k]));//输出必须是String类型的
                    writer.newLine();
                }
    
                writer.flush();
            }
        }
    }
    

不好在哪里

  • 时间复杂度太高,把System输入输出改用BufferedReader和BufferedWriter也超时。每次循环都要找最左边的空桌和一人桌,大可不必,可以利用数据结构使其简便。

2.推荐解法:优先队列

  • 代码

    package 公司食堂;
    
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.PriorityQueue;
    
    /**
     * @author musecho801
     * @title CompanyCanteen1
     * @description 遍历桌号,将所有空桌、一人桌分别入队两个优先队列,
     * 根据性别判断会去哪个桌号
     * @date 2021/3/11 17:21
     */
    public class CompanyCanteen1 {
    
        public void companyCanteen(String peopleDisposeStr, int M, String sexStr, int[] rs) {
            List<PriorityQueue> list = new ArrayList<>(2);
            PriorityQueue<Integer> emptyPQ = new PriorityQueue<>();
            PriorityQueue<Integer> oneTablePQ = new PriorityQueue<>();
            list.add(emptyPQ);
            list.add(oneTablePQ);
            int k = 0;//控制rs的下标
    
            //得到空桌、一人桌 两个优先队列(默认升序)
            //i为 桌号-1
            for (int i = 0; i < peopleDisposeStr.length(); i++) {
                if (peopleDisposeStr.charAt(i) == '0') {
                    emptyPQ.add(i);
                } else if (peopleDisposeStr.charAt(i) == '1') {
                    oneTablePQ.add(i);
                }
            }
    
            //根据性别判断会去哪个桌号
            for (int i = 0; i < sexStr.length(); i++) {
                //男性:只有没有一人桌时,才选择空桌
                if (sexStr.charAt(i) == 'M') {
                    if (oneTablePQ.peek() != null) {
                        rs[k++] = oneTablePQ.poll();
                    } else {
                        oneTablePQ.add(emptyPQ.peek());
                        rs[k++] = emptyPQ.poll();
                    }
                } else if (sexStr.charAt(i) == 'F') {//女性:只有没有空桌时,才选择一人桌
                    if (emptyPQ.peek() != null) {
                        oneTablePQ.add(emptyPQ.peek());
                        rs[k++] = emptyPQ.poll();
                    } else {
                        rs[k++] = oneTablePQ.poll();
                    }
                }
            }
    
            //注意:rs为去第i桌,值要+1
            for (int i = 0; i < M; i++)
                rs[i]++;
        }
    
        public static void main(String[] args) throws IOException {
            CompanyCanteen1 cc = new CompanyCanteen1();
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
    
            int T = Integer.parseInt(reader.readLine());//数据组数
            for (int i = 0; i < T; i++) {
                int N = Integer.parseInt(reader.readLine());//餐桌个数
                String peopleDisposeStr = reader.readLine();//餐桌人数分布
                int M = Integer.parseInt(reader.readLine());//排队人数
                String sexStr = reader.readLine();//排队人的性别
                int[] rs = new int[M];//结果
    
                cc.companyCanteen(peopleDisposeStr, M, sexStr, rs);
                for (int t : rs) {
                    writer.write(Integer.toString(t));
                    writer.newLine();
                }
                //flush()冲刷出流,将所有缓冲数据强制发送至目的地。不加这个,是无法输出的
                writer.flush();
            }
    
        }
    }
    

亮点

  • 使用优先队列直接存储所有空桌、一人桌
  • BufferedReader和BufferedWriter的运行速度较快,学会使用

参考

推荐算法参考:https://blog.nowcoder.net/n/933a93eea0194ebdab05bb464497a0b4

posted @ 2021-03-12 11:39  musecho  阅读(476)  评论(0编辑  收藏  举报