网易笔试题 找朋友 真的是找朋友
2015-09-15 12:07
344 查看
题目 : friend set
时间限制:5000ms
单点时限:1000ms
内存限制:256MB
描述现在存有大量一对好友的列表,好友的好友也是好友,所有有好友关系的形成一个圈子,请找出圈子中的人数。
输入第一行是N,表示好友对的数量(1<= N <= 100000)。之后N行每行是两个数字,代表玩家代号,用空格分隔。玩家代号是整数且<= 1000000000。输出将每个圈子中的人数按降序排列。
样例输入
8
1 2
2 3
5 4
3 4
6 7
8 6
9 10
10 11
样例输出
5
3
3
题目来自2016网易游戏笔试题
我自己的一个想法
看代码
0 这个圈 共有 1 个人
1 2 3 4 5 这个圈 共有 5 个人
6 7 8 这个圈 共有 3 个人
9 10 11 这个圈 共有 3 个人
12 这个圈 共有 1 个人
13 这个圈 共有 1 个人
14 这个圈 共有 1 个人
和朋友聊天,他看了代码后说,用图来解决这种问题是很标准的
但是有点大材小用
确实,如果我给一个测试用例
1
5 2543545
是5号节点与2543545号节点是朋友
而且也只有这一个关系
请问,一共需要多少个节点?
似乎需要2个节点
问题是,2怎么来的?
我还得根据n条关系,找出最少需要几个节点!
用一个list<Relation> reliations装所有的关系
用一个list<Set<Integer>> circles 装所有的圈子(最开始的时候,圈子数为0)
循环遍历每一组关系
判断这组关系是否属于某一个circle(一组关系中的两个参数只要有一个在某个circle中,我们就说这个关系属于这个circle)
判断刚才的那组关系是否属于第二个circle,如果某一个关系同时属于两个circle 我们就把两个circle合并
如何某个关系不属于已知的任何一个circle 那么就新产生一个circle,并把这组关系里的两个值都放进这个新的circle中
遍历circles,输出每个circle的size即可
我觉得这个方法比图更精妙
看代码
时间限制:5000ms
单点时限:1000ms
内存限制:256MB
描述现在存有大量一对好友的列表,好友的好友也是好友,所有有好友关系的形成一个圈子,请找出圈子中的人数。
输入第一行是N,表示好友对的数量(1<= N <= 100000)。之后N行每行是两个数字,代表玩家代号,用空格分隔。玩家代号是整数且<= 1000000000。输出将每个圈子中的人数按降序排列。
样例输入
8
1 2
2 3
5 4
3 4
6 7
8 6
9 10
10 11
样例输出
5
3
3
题目来自2016网易游戏笔试题
我自己的一个想法
图
这其实就是一个给定一个无向图,找出其联通分量的应用看代码
package graph; import java.util.ArrayList; import java.util.LinkedList; import prac.friendset2; public class FriendSet { private ArrayList<Object> vertexList;// 存储点的链表 private int[][] edges;// 邻接矩阵,用来存储边 private int numOfEdges;// 边的数目 public FriendSet(int n) { // 初始化矩阵,一维数组,和边的数目 edges = new int ; vertexList = new ArrayList<Object>(n); numOfEdges = 0; } // 得到结点的个数 public int getNumOfVertex() { return vertexList.size(); } // 得到边的数目 public int getNumOfEdges() { return numOfEdges; } // 返回结点i的数据 public Object getValueByIndex(int i) { return vertexList.get(i); } // 插入结点 public void insertVertex(Object vertex) { vertexList.add(vertexList.size(), vertex); } // 插入边 public void insertEdge(int v1, int v2, int weight) { edges[v1][v2] = weight; numOfEdges++; } // 插入边 public void insertEdge(int v1, int v2) { edges[v1][v2] = 1; edges[v2][v1] = 1; numOfEdges++; } // 得到第一个邻接结点的下标 public int getFirstNeighbor(int index) { for (int j = 0; j < vertexList.size(); j++) { if (edges[index][j] > 0) { return j; } } return -1; } // 根据前一个邻接结点的下标来取得下一个邻接结点 public int getNextNeighbor(int v1, int v2) { for (int j = v2 + 1; j < vertexList.size(); j++) { if (edges[v1][j] > 0) return j; } return -1; } // 私有函数,广度优先遍历 private void broadFirstSearch(boolean[] isVisited, int i) { int u, w; int size=1; LinkedList<Integer> queue = new LinkedList<Integer>(); // 访问结点i System.out.print(getValueByIndex(i) + " "); isVisited[i] = true; // 结点入队列 queue.addLast(i); while (!queue.isEmpty()) { u = ((Integer) queue.removeFirst()).intValue(); w = getFirstNeighbor(u); //u的第1个w节点 while (w != -1) { //一个u 连接n个w if (!isVisited[w]) { size++; // 访问该结点 System.out.print(getValueByIndex(w) + " "); // 标记已被访问 isVisited[w] = true; // 入队列 queue.addLast(w); } // 寻找下一个邻接结点 w = getNextNeighbor(u, w); } } System.out.println("这个圈 共有 "+size+" 个人"); } // 对外公开函数,广度优先遍历 public void broadFirstSearch() { boolean[] isVisited = new boolean[getNumOfVertex()]; int numOfVertex=getNumOfVertex(); for (int i = 0; i < numOfVertex; i++) isVisited[i] = false; for (int i = 0; i < numOfVertex; i++) { if (!isVisited[i]) broadFirstSearch(isVisited, i); } } public static void main(String args[]) { FriendSet graph = getGraph(); graph.broadFirstSearch(); } private static FriendSet getGraph() { int n = 9, e = 9;// 分别代表结点个数和边的数目 FriendSet graph = new FriendSet(15); for (int i=0;i<15;i++) { graph.insertVertex(i);// 插入结点 } // 插入九条边 graph.insertEdge(1, 2); graph.insertEdge(2, 3); graph.insertEdge(5, 4); graph.insertEdge(3, 4); graph.insertEdge(6, 7); graph.insertEdge(8, 6); graph.insertEdge(9, 10); graph.insertEdge(10, 11); return graph; } }输出结果:
0 这个圈 共有 1 个人
1 2 3 4 5 这个圈 共有 5 个人
6 7 8 这个圈 共有 3 个人
9 10 11 这个圈 共有 3 个人
12 这个圈 共有 1 个人
13 这个圈 共有 1 个人
14 这个圈 共有 1 个人
和朋友聊天,他看了代码后说,用图来解决这种问题是很标准的
但是有点大材小用
确实,如果我给一个测试用例
1
5 2543545
是5号节点与2543545号节点是朋友
而且也只有这一个关系
请问,一共需要多少个节点?
似乎需要2个节点
问题是,2怎么来的?
我还得根据n条关系,找出最少需要几个节点!
Circle方法
朋友给出了这样一个想法用一个list<Relation> reliations装所有的关系
用一个list<Set<Integer>> circles 装所有的圈子(最开始的时候,圈子数为0)
循环遍历每一组关系
判断这组关系是否属于某一个circle(一组关系中的两个参数只要有一个在某个circle中,我们就说这个关系属于这个circle)
判断刚才的那组关系是否属于第二个circle,如果某一个关系同时属于两个circle 我们就把两个circle合并
如何某个关系不属于已知的任何一个circle 那么就新产生一个circle,并把这组关系里的两个值都放进这个新的circle中
遍历circles,输出每个circle的size即可
我觉得这个方法比图更精妙
看代码
package prac; /** * Created by zhangchen on 2015/9/14. */ import java.util.*; /** * Created by zhangchen on 2015/9/14. */ public class friendset2 { public static void main(String[] args) { // Scanner scanner = new Scanner(System.in); // int n = scanner.nextInt(); // scanner.nextLine(); // FriendShip[] friendShips = new FriendShip ; // for (int i = 0; i < n; i++) { // friendShips[i] = new FriendShip(); // friendShips[i].f1 = scanner.nextInt(); // friendShips[i].f2 = scanner.nextInt(); // } int n=8; FriendShip[] friendShips = new FriendShip ; getData(friendShips); List<Set<Integer>> circles = new ArrayList<>(); for (int i = 0; i < n; i++) { boolean flag = false; boolean more = false; int connectwith = -1; for (int j = 0; j < circles.size(); j++) { if (circles.get(j).contains(friendShips[i].f1)) { circles.get(j).add(friendShips[i].f2); if (connectwith >= 0 && connectwith != j) more = true; if (connectwith == -1) connectwith = j; flag = true; } else if (circles.get(j).contains(friendShips[i].f2)) { circles.get(j).add(friendShips[i].f1); if (connectwith >= 0 && connectwith != j) more = true; if (connectwith == -1) connectwith = j; flag = true; } if (more) { for (int e : circles.get(j)) { circles.get(connectwith).add(e); } circles.remove(j); } } if (!flag) { Set<Integer> circle = new HashSet<>(); circle.add(friendShips[i].f1); circle.add(friendShips[i].f2); circles.add(circle); } } Collections.sort(circles, new Comparator<Set<Integer>>() { @Override public int compare(Set<Integer> o1, Set<Integer> o2) { return o2.size() - o1.size(); } }); for (int k = 0; k < circles.size(); k++) System.out.println(circles.get(k).size()); } private static void getData(FriendShip[] friendShips) { FriendShip friendShip = new FriendShip(); friendShip.f1 = 1; friendShip.f2 = 2; friendShips[0] = friendShip; friendShip = new FriendShip(); friendShip.f1 = 10; friendShip.f2 = 11; friendShips[1] = friendShip; friendShip = new FriendShip(); friendShip.f1 = 4; friendShip.f2 = 5; friendShips[2] = friendShip; friendShip = new FriendShip(); friendShip.f1 = 4; friendShip.f2 = 3; friendShips[3] = friendShip; friendShip = new FriendShip(); friendShip.f1 = 6; friendShip.f2 = 7; friendShips[4] = friendShip; friendShip = new FriendShip(); friendShip.f1 = 9; friendShip.f2 = 10; friendShips[5] = friendShip; friendShip = new FriendShip(); friendShip.f1 = 3; friendShip.f2 = 2; friendShips[6] = friendShip; friendShip = new FriendShip(); friendShip.f1 = 7; friendShip.f2 = 2; friendShips[7] = friendShip; } } class FriendShip { int f1; int f2; }
参考资料
http://segmentfault.com/a/1190000002685939相关文章推荐
- HDU 4081 Qin Shi Huang's National Road System 最小生成树+倍增求LCA
- SSDB图形化界面管理工具-phpssdbadmin的安装配置
- Java初体验(一)
- [5]startActivityForResult的简单应用
- linux 命令 去掉重复行
- java List转换为字符串并加入分隔符
- 下载安装CocoaPods
- hive如何提交hql语句到hive上执行
- 基于thinkphp的后台管理系统模板快速搭建
- Jump Game
- No Session found for current thread
- go指针的一个小坑
- maven+springmvc错误 JAX-RS (REST Web Services) 2.0 can not be installed
- 杨辉三角
- java常用设计模式学习心得
- 解决ubuntu解压zip文件名乱码的问题
- godaddy空间如何建网站教程
- go指针的一个小坑
- imagebutton 设置点击和按压效果
- [ActionScript 3.0] AS3 3D双圆环贴图