【算法】公司食堂-美团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