在问题陈述中,我有'n'个家庭成员数目很多的家庭。
例如:
John jane (family 1)
tiya (family 2)
Erika (family 3)
我必须以一种不应该与他的家人配对的方式指派所有成员。 输出应该是:
John => tiya
jane => Erika
tiya => jane
Erika => john
我创建了对象Person(name ,familyID, isAllocated)
。
创建了列表并在此中添加了personName_id
。
我正在考虑使用地图进行关联。因此john_1
将成为关键,tiya_2
将成为价值。
我无法通过地图关联这些对。我怎样才能将名单上的成员洗牌。
此外,如果有人能建议我提供更好的解决方案,那就太好了。
代码:
获得人:
public static List getperson()
{
Scanner keyboard = new Scanner(System.in);
String line = null;
int count = 0;
List <Person> people = new ArrayList<>();
while(!(line = keyboard.nextLine()).isEmpty()) {
String[] values = line.split("\\s+");
//System.out.print("entered: " + Arrays.toString(values) + "\n");
int familyid = count++;
for(String name :values)
{
Person person = new Person();
person.setFamilyId(familyid);
person.setName(name);
person.setAllocated(false);
people.add(person);
}
}
return people;
}
映射:
public static List mapGifts(List pesonList)
{
Map<String , String> personMap = new HashMap<String , String>();
Iterator<Person> itr = pesonList.iterator();
Iterator<Person> itr2 = pesonList.iterator();
List<String> sender = new ArrayList<>();
while(itr.hasNext())
{
Person p = itr.next();
sender.add(p.getName()+"_"+p.getFamilyId());
personMap.put(p.getName()+"_"+p.getFamilyId(), "");
// p.setAllocated(true);
}
while(itr2.hasNext())
{
/*if(p.isAllocated())
{*/
// Separate Sender name and id from sender list
//check this id match with new p1.getFamilyId()
for(String sendername :sender)
{
// System.out.println("Sender "+sendername);
personMap.put(sendername, "");
String[] names = sendername.split("_");
String part1 = names[0]; // 004
String familyId = names[1]; // 004
Person p2 = itr2.next();
System.out.println(p2.getFamilyId() +" "+familyId +" "+p2.isAllocated());
if(p2.isAllocated())
{
for ( String value: personMap.values()) {
if ( value != sendername) {
}
}
}
if( p2.getFamilyId() != Integer.parseInt(familyId))
{
// add values in map
}
}
break;
// Person newPerson = personLists.get(j);
}
for (Iterator it = personMap.entrySet().iterator(); it.hasNext();)
{
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println("Gifts "+key+"=>"+value);
}
return pesonList;
}
由于
答案 0 :(得分:0)
从我读过的内容来看,你只关心与人匹配。它们如何匹配并不重要。也就是说,我假设您有一个FamilyID列表,以及每个人的名单,您可以根据家庭ID对人员列表进行排序。
我们打电话给他们:
List<FamilyID> families;
和
分别为LinkedList<Person> people;
。 (您可以将FamilyID设为枚举类)
我们需要两个哈希图。一个给出familyID的家庭成员的列表(基本上是邻接列表):
HashMap<FamilyID, List<Person>> familyMembers;
,
和一个生成发送者(密钥)和接收者(值)对的列表:
HashMap<Person, Person> pairs;
一个有用的功能可能是,当给出一个人及其家庭ID时,我们可以找到可以从他们那里接收的下一个可用的人。
String generateReceiver(Person newSender, FamilyID familyID);
这种方法的实现应该非常简单。您可以遍历人员列表并检查当前人员是否不是家庭成员。如果该条件通过,则将其从“人员”列表中删除,这样您就不会再次尝试迭代它们。如果您正在使用链接列表,则删除为O(1),因为您已经拥有该引用。在遍历的最坏情况列表是n + n - 1 + ... + 2次以获得O(n ^ 2)时间效率(即,您有一个大家庭和许多小家庭)。解决这个问题的方法是抛弃LinkedList,使用基于数组的列表,并保留一个单独的索引值数组,这些索引值对应于每个“当前可用的指定系列接收器”。当您将每个家庭的人员添加到人员列表时,您将初始化这些值(即,家庭1的开始是索引“0”;如果家庭1有2个人,则家庭2的开始将是索引“2”)。如果您每次添加发送器 - 接收器对时只增加当前可用的接收器索引,这将使函数O(1)成为时间。 (如果你想了解更多细节,请给我留言!)
最后但并非最不重要的是,循环正在为所有人这样做。
for (List<Person> family : familyMembers)
for (Person person : family)
{
// get the next available receiver who is not a family member
// add the family member and its receiver to "pairs" hash
}
请注意,上面的循环是伪代码。如果您想知道是否使用此方法生成冲突的接收器/发送器,则不会。人员列表基本上充当接收者列表。无论您采用people
列表的哪种方式,generateReceiver(...)
都会消除算法看到错误接收器的可能性。根据效率,如果您执行基于数组的实现,那么您将在O(N)时间生成所有对值,其中N是总人数。程序本身也是O(N)空间。
当然,这完全基于您有足够的人匹配发送者 - 接收者对的假设。你需要添加铃声和口哨来检查特殊情况。
希望这有帮助!祝你好运!