从n ^ 2减少时间复杂度

时间:2019-03-01 18:36:15

标签: algorithm data-structures

全班有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),并且我正在寻找一个更好的解决方案。谢谢!

1 个答案:

答案 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)