- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
问题陈述
人们在社交网络中相互联系。人 I 和人 J 之间的连接表示为 M I J。当属于不同社区的两个人连接时,净效果是 I 和 J 所属的两个社区的合并。
一开始,有N个人代表N个社区。假设人 1 和 2 连接,后来 2 和 3 连接,那么 1,2 和 3 将属于同一个社区。
有两种类型的查询:
M I J => 包含个人 I 和 J 的社区合并(如果他们属于不同的社区)。
Q I => 打印我所属社区的大小。
我的方法:
我创建了一组空集合。当两个人合并时,我正在检查所有内部集合,如果找到其中任何一个,我将它们添加到那个集合中并突破。如果不是,我正在与这些人一起创建一个新的内部集合。现在在这个父集中,我需要将所有内部集相互比较,如果找到交集,我应该将两个内部集组合起来,这是我做不到的。
我的方法正确吗?但这是一个非常迭代的过程,有没有更好的方法来解决呢?
我的代码:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
Scanner sc = new Scanner(System.in);
int nPeople = sc.nextInt();
int queries = sc.nextInt();
Set<Set<Integer>> community = new HashSet<Set<Integer>>();
for(int i = 0 ; i<queries ; i++){
char query = sc.next().charAt(0);
if(query == 'Q'){
int p = sc.nextInt();
Set<Integer> tmpset = new HashSet<Integer>();
for( Set<Integer> innerSet : community){
for(Integer person : innerSet) {
if( person == p ){
for(Integer each : innerSet){
tmpset.add(each);
}
}
}
}
if(tmpset.size()!= 0) {
System.out.println(tmpset.size());
}
else {
System.out.println("1");
}
}
else if(query=='M'){
int person1 = sc.nextInt();
int person2 = sc.nextInt();
int c = 0;
loop:
for( Set<Integer> innerSet : community){
for(Integer person : innerSet) {
if( person == person1 || person == person2){
innerSet.add(person1);
innerSet.add(person2);
c++;
break loop;
}
}
}
if(c==0){
Set<Integer> tmpset = new HashSet<Integer>();
tmpset.add(person1);
tmpset.add(person2);
community.add(tmpset);
}
}
}
}
}
我的代码输出:包含集合的集合。
问题链接:https://www.hackerrank.com/challenges/merging-communities
在@Adamski 的帮助下解决了它,使用了不相交的集合数据结构,但仍然不是那么有效的解决方案。
代码:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
Scanner sc = new Scanner(System.in);
int nPeople = sc.nextInt();
DisJoint comm = new DisJoint(nPeople);
int queries = sc.nextInt();
for(int k = 0 ; k<queries ; k++){
char query = sc.next().charAt(0);
if(query == 'Q'){
int person = sc.nextInt();
int personParent = comm.Find(person);
int community = 0;
for(int j =1 ; j<nPeople+1 ; j++){
int tmpParent = comm.Find(j);
if(personParent == tmpParent){
community++;
}
}
System.out.println(community);
}
if(query == 'M'){
int person1 = sc.nextInt();
int person2 = sc.nextInt();
comm.Union(person1,person2);
}
}
}
}
class DisJoint{
public int Count;
public int[] Parent;
public int[] Rank;
public DisJoint(int count){
this.Count = count;
this.Parent = new int[this.Count+1];
this.Rank = new int[this.Count+1];
for (int i = 1; i < this.Count+1; i++) {
this.Parent[i] = i;
this.Rank[i] = 0;
}
}
public int Find(int i){
if(i == Parent[i]){
return Parent[i];
}
else{
int result = Find(Parent[i]);
Parent[i] = result;
return result;
}
}
public void Union(int a, int b){
if(a>b){
int tmp = a;
a = b;
b = tmp;
}
int aroot = this.Find(a);
int broot = this.Find(b);
int arank = Rank[aroot];
int brank = Rank[broot];
if (aroot == broot){
return;
}
if (arank < brank) {
this.Parent[aroot] = broot;
}
else if (arank > brank) {
this.Parent[broot] = aroot;
}
else{
this.Parent[aroot] = broot;
Rank[broot]++;
}
}
}
请测试上述链接中的代码。
最佳答案
您是否考虑过使用数据结构来表示不相交的集合?例如这里:http://www.mathblog.dk/disjoint-set-data-structure/
基本前提是您定义一个类(例如 Person
)并将您的社区集表示为单个数组。每个Person
包含返回数组的索引,指向自身或另一个 Person
:
| Adam | Dave | Fred | Tom | James |
| 0 | 0 | 1 | 3 | 3 |
在上面的示例中,要测试 Fred 和 Dave 是否在同一个社区中,您从每个人开始,然后按照图表找到根人;即索引引用自身的人:
Fred -> Dave -> Adam
Dave -> Adam
(显然这里有一个优化,在第一次遍历期间,您实际上在到达根目录之前遇到了 Dave。)
对比一下,测试James和Fred是否在同一个社区:
James -> Tom
Fred -> Dave -> Adam
人有不同的根源,因此属于不同的社区。
合并社区就是将一个社区的根人重新指向另一个社区的根。
推断社区的规模更为复杂;我将把它作为练习留给你去弄清楚!
关于java - 合并社区并通过其成员找到社区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31452639/
我有几个长度不等的 vector ,我想对其进行cbind。我将 vector 放入列表中,并尝试结合使用do.call(cbind, ...): nm <- list(1:8, 3:8, 1:5)
合并(合并)两个 JSONObjects 的最佳方式是什么? JSONObject o1 = { "one": "1", "two": "2", "three": "3" }
我在一个表中有许多空间实体,其中有一个名为 Boundaries 的 geometry 字段。我想生成一个具有简化形状/几何图形的 GeoJson 文件。 这是我的第一次尝试: var entitie
谁能说出为什么这个选择返回 3.0 而不是 3.5: SELECT coalesce(1.0*(7/2),0) as foo 这个返回 3: SELECT coalesce(7/2,0) as foo
首先抱歉,也许这个问题已经提出,但我找不到任何可以帮助我的东西,可能是因为我对 XSLT 缺乏了解。 我有以下 XML: 0 OK
有时用户会使用 Windows 资源管理器复制文件并在他们应该执行 svn 存储库级别的复制或合并时提交它们。因此,SVN 没有正确跟踪这些变化。一旦我发现这一点,损坏显然已经完成,并且可能已经对相关
我想组合/堆叠 2 个不同列的值并获得唯一值。 如果范围相邻,则可以正常工作。例如: =UNIQUE(FILTERXML(""&SUBSTITUTE(TEXTJOIN(",",TRUE,TRANSPO
使用iTextSharp,如何将多个PDF合并为一个PDF,而又不丢失每个PDF中的“表单字段”及其属性? (我希望有一个使用来自数据库的流的示例,但文件系统也可以) 我发现this code可以正常
是否有一个合并函数可以优先考虑公共(public)变量中的非缺失值? 考虑以下示例。 首先,我们生成两个 data.frames,它们具有相同的 ID,但在特定变量上有互补的缺失值: set.seed
我们正在尝试实现 ALM Rangers 在最新的 Visual Studio TFS Branching and Merging Guide 中描述的“基本双分支计划”。 .从指导: The bas
我在不同目录(3个不同名称)中有很多(3个只是一个例子)文本文件,如下所示: 目录:A,文件名:run.txt 格式:txt制表符分隔 ; file one 10 0.2 0.5 0.
我有一张包含学生等级关系的表: Student Grade StartDate EndDate 1 1 09/01/2009 NULL 2
我在学习 https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-associatio
我觉得我有世界上最简单的 SVN 用例: 我有一个文件,Test.java在 trunk SVN的。 我分行trunk至 dev-branch . 我搬家Test.java进入 com/mycompa
我有两个数据框,其中一些列名称相同,而另一些列名称不同。数据框看起来像这样: df1 ID hello world hockey soccer 1 1 NA NA
Elasticsearch 中是否缺少以扁平化形式(多个子/子aggs)返回结果的方法? 例如,当前我正在尝试获取所有产品类型及其状态(在线/离线)。 这就是我最终得到的: aggs [ { key:
如何合并如下所示的 map : Map1 = Map(1 -> Class1(1), 2 -> Class1(2)) Map2 = Map(2 -> Class2(1), 3 -> Class2(2)
我试图通过从netezza服务器导入数据来合并两个数据集。 以下是数据集,其数字为,ID为,字母为,名称为: 下表都是使用命令从netezza导入的: sqoop import --connect n
我有两个数组 $array1 = array('first', 'second', 'third', 'fourth'); $array2 = array('first', 'third', 'fou
我正在 SQL Server 中运行合并。在我的更新中,我只想在值发生更改时更新该行。有一个版本行在每次更新时都会递增。下面是一个例子: MERGE Employee as tgt USING (SE
我是一名优秀的程序员,十分优秀!