合并n个列表并对数据进行排序,以保持原始顺序/约束

时间:2019-02-24 18:21:24

标签: java algorithm sorting merge comparator

我在编码比赛中遇到了以下问题。我尝试了很多,但是一个私人测试用例总是对我失败,给出错误的答案,并且我无法弄清楚为什么我的下面的方法会失败。我没有天真的解决方案来生成压力测试用例并进行比较。此外,也不会发表社论。 因此,我正在寻找可以指出我方法中缺陷的人。

以下是对该问题的详细说明,以及我到目前为止尝试过的内容。

问题: 有多个区域,每个区域的学生会根据他们在相应区域中的排名获得分数。 例如:

Region1:
StudentName, Score
A,           50.0
B,           60.0  
C,           40.0 

Region2:
StudentName, Score
D,           30.0
E,           10.0
F,           20.0 

在以上数据中,学生A在Region1中排名1,B在Region1中排名2,C在Region1中排名3。 同样,D在Region2中具有Rank1,E具有Rank2,F具有Rank3。

  • 学生在同一地区的得分可能会更低,但排名仍然更高。例如,在Region1中,A的排名优于B,也就是说,我们应该假设每个区域的数据已经根据排名进行了排序。

我们的任务是合并所有区域的数据并创建根据得分排名的全局数据。约束条件是,该区域中排名较低的任何学生,其排名都不能高于该区域中其他学生的排名,而该排名要高于原始区域数据中的排名。

例如:

Region1:
A, 50.0
B, 60.0
C, 40.0 

Region2:
D, 30.0
E, 10.0
F, 20.0

将合并为:

A, 50.0
B, 60.0
C, 40.0 
D, 30.0
E, 10.0
F, 20.0

顺序没有根据分数改变,因为根据区域约束,B总是低于A,F总是低于E。

其他测试用例:

Region1:
A, 50.0
B, 60.0
C, 70.0 

Region2:
D, 30.0
E, 20.0
F, 10.0

再次按照A,B,C,D,E,F的顺序

Region1:
A, 60.0
B, 80.0
C, 100.0 

Region2:
D, 70.0
E, 90.0
F, 110.0

将导致: D,E,F,A,B,C

但是

Region1:
A, 11.5
B, 8.5
C, 10.0 

Region2:
D, 12.0
E, 9.0
F, 9.5

将导致:

D, 12.0
A, 11.5
E, 9.0 
B, 8.5
C, 10.0
F, 9.5

Constraints:
1<=number of regions<=6
score can be upto 7 decimal places

我的方法是将所有输入数据添加到一个列表中并保持稳定的排序,即如果两个学生的区域相同,则比较他们在区域中的排名,否则比较分数。

static class Student implements Comparable<Student>
{
String name;
double score;
int zone;
int rank;

//constructor

public int compareTo(Student o)
{
if(this.zone == o.zone)
{
//lower i.e. better rank
return Integer.compare(this.rank, o.rank);
}
//higher i.e. better score
return Double.compare(o.score, this.score);
}

}

main()
{
//read data from console input into an ArrayList<Student> students
Collections.sort(students);
//print each student from students

}

该问题未提及在不同地区的两名学生的分数是否相等。在这种情况下,我尝试使用各自在区域中的等级打破平局,但私人测试用例始终失败。我最初以为该问题可能缺少一些信息,但是我在比赛仪表板中看到许多成功提交该问题的信息。这就是我认为我缺少某些东西的原因,问题并不像我想的那么简单。但是,我无法提出一个测试案例来验证这一假设。

谢谢!

2 个答案:

答案 0 :(得分:2)

据我了解的问题,要求是根据分数对学生进行排序,但附加的约束条件是保留区域内学生的相对顺序。

从问题中列出的示例之一获得输入数据,

Region1:
A, 11.5
B, 8.5
C, 10.0 

Region2:
D, 12.0
E, 9.0
F, 9.5

仅按分数排序会得到以下结果:DACFEB。

但是,要保持一个区域内的相对顺序,就需要以下偏序 A

OP将这个特定示例的解决方案称为DAEBCF。在对该问题的评论中,我为该示例提出了另外两种可能的解决方案:DABCEF和DAEFBC。我看不到任何标准可以让我们决定这些可能的解决方案中哪一个是正确的。这样,问题就受到限制。一个人可以争论哪种解决方案比其他解决方案更可取,但是这样做会引入新的约束条件,而这些约束条件在原始问题中并未得到证实。

鉴于有多个解决方案可以满足问题中的所有条件,这意味着该域中没有总排序。此外,鉴于正确的比较器必须对其域的值强加一个总排序,因此无法为该域编写适当的比较器。

当然,可以编写具有某些行为的正确Comparator,并且它会优先选择其中的一种。这样做将隐式地实现不是问题陈述一部分的其他约束。实际上,看来Vincent van der Weele已经这样做了。语句“下一个空白点必须由一个区域中排名最高的剩余元素填充。哪个?得分最高的那个”引入了附加约束。这将导致OPEB建议订购DAEBCF。尽管这很明智,但是必然是“正确”的排序。

另一种算法可能如下。 1)从一个空的结果列表开始,并按排名顺序维护每个地区的学生列表。 2)查找得分最高的其余学生。 3)将该学生和同一地区的高等学生带入结果中,并保持相对顺序。 4)重复直到没有学生。

将此算法应用于示例输入结果会产生DABCEF。这是明智的,但是以不同的方式。同样,我们不知道这是否是正确的答案。

要么编程竞赛中的问题最初没有被指定,要么在竞赛的问题陈述和堆栈溢出中OP的问题之间丢失了一些信息。

答案 1 :(得分:1)

您的比较器不正确。您基本上说的是,如果学生来自同一地区,则按等级排序,否则按分数排序。但这是不正确的,如此示例所示:

Region1:
A, 11.5
B, 8.5
C, 10.0 

Region2:
D, 12.0
E, 9.0
F, 9.5

产生

D, 12.0
A, 11.5
E, 9.0 
B, 8.5
C, 10.0
F, 9.5

即,得分9.0的E排在得分10.0的C之前,即使他们来自不同地区。


一个更有效的简单算法:

逐个元素填充结果。下一个空白点必须由其中一个区域中排名最高的剩余元素填充。哪一个?得分最高的那个。因此,请将该元素从其区域中删除,将其添加到结果中,然后重复进行直到完成。