全班有n
个学生。很快,将有一个跨学校科学测验,其中将有关于4个主题的问题,为简单起见,分别称为1,2,3和4。小组中应有2名学生。任何学生在特定学科上的好坏均同样可能。
我们将n行作为输入,每行有4个条目。如果第i
列等于1,则该学生擅长第i
个科目。我应该找出学校派遣团队的总数,以便这两个学生一起知道这四个科目。
例如
S1: 1 1 1 1
S2: 1 1 0 1
S3: 1 0 1 1
S4: 0 0 1 1
S5: 0 0 0 0
由于所有科目都是他的强项,因此学生1可以和任何学生一起去。 => 4
由于S2在科目1,2和4中都很好,而S3和S4在科目3中是很好,所以学生2可以与S3和S4并驾齐驱。 >
S3会在主题2 =>无的情况下获得一个好成绩
S4:同样,没有。
因此,ans = 4 + 2 = 6
我的解决方案:-
ans=0;
//arr is the array containing subject-wise "strength" of students
for(int i=0;i<n;i++){
ArrayList<Integer> a=new ArrayList<>();
for(int j=0;j<4;j++)
if(arr[i][j]==0)
a.add(j);
if(a.size()==0)
ans+=n-i-1;
else
for(int j=i+1;j<n;j++){
bool=false;
for(int k=0;k<a.size();k++){
if(arr[j][a.get(k)]==0)
break;
bool=true;
}
if(bool)
ans++;
}
}
System.out.println(ans);
现在我知道我的解决方案是正确的,但是它的时间复杂度为O(n ^ 2),并且我正在寻找一个更好的解决方案。谢谢!
答案 0 :(得分:4)
您可以通过为各个学科的组合花费记忆来减少学生数量的复杂性。
构建2 ^ {s
个元素的列表,其中s
是主题的数量。按主题组合索引列表,解释为二进制数。例如,S2
的值为13,而缺少的值为2。
首先计算每个学生可以满足的“需求”。对于学生已知科目中的1
位的每种组合,请增加提示列表的索引。
for student in student_list:
score = # student's covered subjects as an int
tally = [0]*16
for idx in range(16):
if idx & score == idx:
tally[idx] += 1
您现在有了一个列表,其中列出了可以涵盖所需学科的每种组合的学生人数。这是 O(n * 2 ^ s)
为每个学生找到所需分数,即学生分数的1的补码。现在,简单地添加所有得分所需的得分记录即可。
team_ct = 0
for student in student_list:
needed = # student's needed subjects as an int; this is 15-score (above)
team_ct += tally[needed]
现在,每个配对都被计数了两次,因此将team_ct
除以2。
是的,可以将这最后一部分代码放入一个代码行中:
team_ct = sum([tally[15-score] for score in foo]) / 2
foo
是所有学生分数的构成。这部分是 O(n)。