java某校在积极推行无人监考,JD面试 || 移除教室人数

在昨天参加了东哥的笔试,选择题做的还算可以,但是还有道编程题和关于jdk8的Stream特性难住了。鉴于此用博客总结一下这道编程题,并结合Stream特性来简化代码,熟悉Api。

题目描述

某校在积极推行无人监考制度,但是总有学生是不自觉的,如果将两个很熟的异性朋友放在同一个考场里,他们就会交流甚至作弊。因此一个考场中不能允许两个很熟的异性朋友存在,学校希望通过搬出一部分学生的方法来改善这一问题。但是又因为教室数量有限,因此希望一个教室中容下的学生尽可能多,即需要搬出教室的学生数量尽可能少,请你输出搬出教室人数最少,且字典序最小的方案。

输入

输入第一行有两个整数n和m,分别表示有n个男生和n个女生,有m个朋友关系。(1<=n<=500,1<=m<=100000)接下来m行,每行有两个整数,x和y,表示第x号男生和第y号女生是朋友。

男生的编号均为[1,n],女生的编号为[n+1,2n]。

输出

输出第一行包含一个整数a,表示最少需要搬出教室的人数。

输出第二行有a个整数,即a个需要搬出教室的人的编号,要求人数最少,且字典序最小。

意思是:一个教室内不能有亲密关系的男女,选择要移除的人满足尽可能的少、学号尽可能的小。

思路

按照题目描述可以明确:移除人数最少代表先移除不止和一个人有关系的同学。学号尽可能的小代表着优先移除男生。它的优先级是:人数>学号。

有了这个目标,再来确定算法的数据结构,我运用了以下的数据结构:

1 //维护每个学生的关系映射,一对多的关系

2 Map> relationmap = new HashMap<>(16);

3

4 //某个学生的关系具体学号

5 List templist = relationmap.getOrDefault(boynum, new ArrayList<>());

6

7 //存放男女生有关系的个数,男生与女生各n个,第一位不放数据。

8 int[] relation = new int[2*n+1];

然后利用伪代码来具体描述这个过程:

获得输入的男生人数n和关系m;

初始化relation数组,map;

for( m个关系){

接收男生与女生的关系;

将两个学号作key放入Map中;

把另一个学号作value放入map的List中;

以两个学号为下标的relation数组加一;

}

while(true){

从头到尾遍历relation数组,获得最大值的下标maxRelationIndex;

当maxRelationIndex==0,意味着当前没有亲密关系,break;

根据maxRelationIndex获得map中的关系结合list;

for(list){

遍历list,将对应的relation数组的下标-1;

}

删除以学号为索引在relation数组的记录;

记录被删除的学号。

}

输出记录:

代码实现

1 import java.util.*;

2

3 /**

4 * TODO

5 * @Author: HILL

6 * @date: 2019/8/25 9:50

7 *

8 **/

9 public class Main {

10 public static void main(String[] args) {

11

12 //维护关系映射

13 Map> relationmap = new HashMap<>(16);

14 //男女生人数

15 Scanner sc = new Scanner(System.in);

16 int n = sc.nextInt();

17 int m = sc.nextInt();

18

19 //存放男女生有关系的个数

20 int[] relation = new int[2*n+1];

21

22

23 for (int i=0;i

24 int boynum = sc.nextInt();

25 int girlnum = sc.nextInt();

26

27 //添加男生关系映射

28 List templist = relationmap.getOrDefault(boynum, new ArrayList<>());

29 templist.add(girlnum);

30 relationmap.put(boynum,templist);

31 //添加女生关系映射

32 templist = relationmap.getOrDefault(girlnum, new ArrayList<>());

33 templist.add(boynum);

34 relationmap.put(girlnum,templist);

35 //维护每个人的关系度的权值,越大代表与越多人有关系

36 relation[girlnum]++;

37 relation[boynum]++;

38

39

40 }

41 List result = new ArrayList<>();

42 while (true){

43 int maxRelationIndex = 0;

44

45 //从头到尾遍历,优先移除男生

46 for (int i=1 ;i

47 if (relation[i]>maxRelationIndex){

48 maxRelationIndex = i;

49 }

50 }

51 //当教室里没有亲密关系时

52 if (maxRelationIndex == 0){

53 break;

54 }

55

56 //优先移除与最多人有关系的学生

57 relation[maxRelationIndex] = 0;

58 //查出所有与被移除学生有关系的学生

59 List list = relationmap.get(maxRelationIndex);

60 //将它们的关系计数-1

61 list.forEach(i-> relation[i]--);

62

63 //将移除的学生加入到结果集

64 result.add(maxRelationIndex);

65 relationmap.remove(maxRelationIndex);

66 }

67 System.out.println(result.size());

68 result.forEach(num->System.out.print(num+" "));

69

70 }

71 }

提醒

以上代码仅供交流参考,用例不一定全部通过,因为当我想出来时已经没时间了。从总体上分析,性能估计不会很高,毕竟一个算法下来会有两次循环,同时空间复杂度也比较高。但能做一步是一步嘛,后面再看看能不能换个思路。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值