Snapchat- Group Record using Union-find

最近一直在做面筋,就没有在这边更新!但是最近!没有偷懒!

// 题目是手机上的通讯录,每条记录只有(name, number)这种pair,有些记录名字重复,有些记录号码重复,让我返回一个list<list<Record>>,
// 将所有记录按人分组。比较tricky的点在于(ABC,123), (ABC, 456), (BCD, 456)
// 三条记录,第一条和第三条也属于同一个人。要求时间复杂度尽量小

uf算法我是明白的,但是我想的时候的困惑在于

1.ufMap里面存放什么,是map<Record, Record>还是map<String, String>还是别的什么

2.在group的时候,既要对name进行uf group又要对number进行group怎么操作

解决方案是这样的(既union-find部分的思路)

 1 1.首先ufMap里面存<Record, Record>,初始化把所有entry过一遍,都存入,使它最初的root节点都是它自己
 2
 3 2. find部分。
 4
 5   1)首先找到这个record的root节点
 6
 7   2)然后把从这个record开始直到root节点所有的节点的root节点都更新成root
 8
 9   3)返回root
10
11 3. union部分,没什么特别的
12
13   1)对record1,record2找到root1,root2
14
15   2)如果root1 != root2,那么就设置其中一个是另外一个的root节点

完成union-find的部分,整个算法的整体思路是。

 1 1.建立一个nameMap<nameString, Record>和一个numMap<number, Record>
 2
 3 2.对于所有entry走一遍,
 4
 5   1) 如果nameMap里面已经存在当前entry的name,那么就说明要union;否则就把[nameString, entry]加入map
 6
 7   2)如果numMap里面已经存在当前entry的number,那么就说明要union;否则就把[number, entry]加入map
 8 3. 所以此刻ufMap里面已经有已经对于name和number group之后的结果,现在就需要把结果保存下来。
 9
10   所以可以先建一个Map<String, List<Record>>整理好,再根据这个map得到List<List<Record>>

实际代码如下:

 1 public class GroupRecord {
 2     static class Record {
 3         String name;
 4         int number;
 5         public Record(String name, int number) {
 6             this.name = name;
 7             this.number = number;
 8         }
 9
10         public String toString() {
11             return "(" + name + "," + number + ")";
12         }
13     }
14
15     public static List<List<Record>> group(List<Record> records) {
16         Map<Record, Record> ufMap = new HashMap<Record, Record>();
17         Map<String, Record> nameMap = new HashMap<>();
18         Map<Integer, Record> numMap = new HashMap<>();
19         for(Record entry: records) {
20             ufMap.put(entry, entry);
21         }
22         for(Record entry: records) {
23             if(nameMap.containsKey(entry.name)) {
24                 union(ufMap, entry, nameMap.get(entry.name));
25             } else {
26                 nameMap.put(entry.name, entry);
27             }
28             if(numMap.containsKey(entry.number)) {
29                 union(ufMap, entry, numMap.get(entry.number));
30             } else {
31                 numMap.put(entry.number, entry);
32             }
33         }
34         Map<String, List<Record>> groupMap = new HashMap<>();
35         for(Record entry: records) {
36             Record root = find(ufMap, entry);
37             List<Record> list = groupMap.get(root.name);
38             if(list == null) {
39                 list = new ArrayList<Record>();
40             }
41             list.add(entry);
42             groupMap.put(root.name, list);
43         }
44         List<List<Record>> res = new ArrayList<List<Record>>(groupMap.values());
45         return res;
46     }
47
48     private static Record find(Map<Record, Record> ufMap, Record record) {
49         Record root = record;
50         while(!ufMap.get(root).equals(root)) {
51             root = ufMap.get(root);
52         }
53         Record cur = record;
54         while(!cur.equals(root)) {
55             ufMap.put(record, root);
56             cur = ufMap.get(cur);
57         }
58         return root;
59     }
60
61     private static void union(Map<Record, Record> ufMap, Record r1, Record r2) {
62         Record root1 = find(ufMap, r1);
63         Record root2 = find(ufMap, r2);
64         if(!root1.equals(root2)) {
65             ufMap.put(root1, root2);
66         }
67     }
68
69     public static void main(String[] args) {
70         List<List<Record>> res = new ArrayList<List<Record>>();
71         ArrayList<Record> records = new ArrayList<>();
72         records.add(new Record("ABC",123));
73         records.add(new Record("ABC",456));
74         records.add(new Record("BCD",456));
75
76         records.add(new Record("AD",342));
77         records.add(new Record("AddD",11));
78         records.add(new Record("DFX",34));
79         records.add(new Record("AD",34));
80         records.add(new Record("AD",11));
81
82         res = group(records);
83         System.out.println(res);
84     }
85 }
时间: 2024-10-03 13:10:14

Snapchat- Group Record using Union-find的相关文章

group By 和 Union 、 Union all的用法

我学习的是MySQL,学习写sql语句过程中遇到Group By 和 Union. 大家乐意看这两个链接,写的很好 Group By: www.cnblogs.com/rainman/archive/2013/05/01/3053703.html Union : http://www.jb51.net/article/48933.htm 博主只是为了加强记忆才写博客的,基本上是盗用 首先我们来看什么是group By. Group By 就是分组的意思,根据***分组 这是原始表 select

MySQL查询子句(group by,limit,union,order by等)

Order by 按照字段值进行排序,默认升序(asc).校对规则决定排序关系. order by 字段 升序|降序(asc|desc), Order by允许多字段排序. 指的是,先按第一个字段排序,如果不能区分,才使用第二个字段,以此类推. create table test( id int primary key not null auto_increment, name varchar(10), group_id int ); insert into test values(null,'

GROUP BY的扩展

GROUP BY的扩展主要包括ROLLUP,CUBE,GROUPING SETS三种形式. ROLLUP rollup相对于简单的分组合计增加了小计和合计,解释起来会比较抽象,下面我们来看看具体事例. 例1,统计不同部门工资的总和和所有部门工资的总和. SQL> select deptno,sum(sal) from emp group by rollup(deptno); DEPTNO SUM(SAL) ---------- ---------- 10 8750 20 10875 30 940

Oracle高级查询之GROUP BY

对于group by 的方式不再累赘,高级方式如下案例. 参考老师文章:http://blog.csdn.net/fu0208/article/details/7183258,向老师致敬,辛苦了 为了方便大家学习和测试,所有的例子都是在Oracle自带用户Scott下建立的.所用emp表, 如果没有此表请参考文章:http://blog.csdn.net/xiaokui_wingfly/article/details/43957003中拷贝 现在客户的需求是统计部门中每种工作的工资总额,最后还需

3.UNION

--联合结果集union(集合运算符-- select StudentNo as nonono,SUM(StudentResult) from Result where StudentNo=1 group by StudentNo union select StudentNo as no,aa='22' from Result where StudentNo=2 ---union可以合并多个结果集 --它有两个前提和一个注意: --1.合并的结果集的列数必须完全一致 --2.合并的多个结果集的对

使用group by 来统计的小作业

# group by 加子句 with rollup 用法DELIMITER $$ USE `bank`$$ DROP PROCEDURE IF EXISTS `dearSUM`$$CREATE      PROCEDURE `bank`.`dearSUM`(    IN i_pass CHAR(6)    )      BEGIN    IF (i_pass = "123456") THEN             SELECT tradeType, SUM(tradeMoney) 

mysql中的左连接,右连接,内连接,union

1,左连接时,第一个表中的所需的数据全要,第二个表中如果没有相应匹配的数据则补null. 2,右连接时,第二个表中的所需数据全要,第一个表中如果没有相应匹配的数据则补null. 3,内连接时,只有第一个表和第二个表中有相应数据匹配时才要,如果其中一个表没有相应的数据匹配则不要. 4,union可以连接2个select的查询结果,前提是所查询的列数相同,且查询的字段以第一个表的字段为字段名,查询结果去除相同行的数据,如果使用union all则可以达到外连接,即获取所有行的数据(包括相同的行)的结

解决部分月份绩效无法显示的问题:timestamp\union al\autocommit等的用法

绩效部同事反映部分员工绩效在查询时无法显示,并给出了两个工号.这两个工号对应绩效全部正常审批完成,但在绩效管理模块却无法显示.绩效管理采用分页查询,查询语句为: <!-- 绩效查询集合  --> <select id="queryList" resultMap="PerformanceResultMap"  parameterType="com.fx.oa.module.per.performance.api.shared.domain.

Oracle中group by 的扩展函数rollup、cube、grouping sets

Oracle的group by除了基本用法以外,还有3种扩展用法,分别是rollup.cube.grouping sets,分别介绍如下: 1.rollup 对数据库表emp,假设其中两个字段名为a,b,c. 如果使用group by rollup(a,b),首先会对(a,b)进行group by ,然后对 a 进行 group by ,最后对全表进行 group by 操作. 如下查询结果: 查询语句 Select deptno,job,sum(sal) from emp group by r

员工薪资历史-Union实现

( 2010-8-27 记录)员工薪资历史 -Union 实现: 1.  表结构 Salary ( id , empID , jbxz,yfxz,sfxz,jse , pid ) Perion(id,bm,year,month,sdate,edate-) 表结构大体是这样的,其中 bm 是薪资日期编码如 2010-8 ,但是不一定也可以是 108 ,无规则可言. Year 是薪资年, month 是薪资月, sdate 和 edate 是开始和结束日期. 2.    本来打算用交叉表实现的,原本