如何创建更优化的解决方案

时间:2018-09-17 05:30:40

标签: java

因此,我的老师通常会给我们分配一些问题,例如一些用于练习的hackerrank。当前有一个具体问题正在困扰我,如下。

一所学校正在举行一项竞赛,以测试学生的知识。一个由五个学生组成的团队,每个学生都精通学校提供的五个科目之一。在学校教授的科目是物理学(p),化学(c),数学(m),植物学(b),动物学(z)。每个团队可以有五个学生,一个学生不能加入两个团队,每个团队每个科目只有一个人。因此,团队中不会有两个擅长物理学的人。

我的任务是,给定一个字符串,该字符串与仅由该领域的技能确定的学生列表有关,以确定可以组建多少团队。

例如,

pcmpcmbbbzz将返回2 pcmpp将返回0

static int differentTeams(String skills) {
    char [] c1 = skills.toCharArray();
    //number of students that can be on a team
    int max = 5;
    //create set of characters for any team instance which can be max of 5
    Set<Character> teamSet = new HashSet<Character>();
    //create set of used characters or indexs in this string
    Set<Integer> insertedSet = new HashSet<Integer>();
    int i = 0;
    int numberOfTeams = 0;
    //iterate through the array of chars
    while(i < c1.length){
        if(teamSet.contains(c1[i]) || insertedSet.contains(i)){
            //if the specific character or study type has been added to the team or it has been used 
            //skip over it and proceed to the next thing
            i++;
            continue;
        }
        //if none of these if blocks execute that means it can be added to the team.
        //also need to keep track of the fact that it was inserted because a student can only be
        //on one team
        teamSet.add(c1[i]);
        insertedSet.add(i);
        i++;

    if(teamSet.size() % max == 0 && teamSet.size() > 0){
            //signals that a complete team of five people have been created
            //empty the set
            teamSet.clear();
            //increment the number of teams
            numberOfTeams++;
            //reset i
            i = 0;
        }
    }
    return numberOfTeams;
}

这是我到目前为止的内容,我的思想过程可以在评论中看到。但是,对于某些测试用例,它超时了,这意味着查找解决方案所花的时间比给定的时间更长。显然,我的解决方案是幼稚的,甚至是蛮力的,因为我迷失了自己,所以有什么方法可以优化我已经拥有的东西。

4 个答案:

答案 0 :(得分:6)

尝试一下。这个想法是创建五个主题的计数数组。创建此数组后,您要做的就是迭代字符串,找到所需的字符(p,c,m,b,z -> 0,1,2,3,4)并增加计数。由于需要尽可能少的团队,因此需要在五个值中找到最小值。这样可以为您提供最少的团队人数。

static int differentTeams(String skills) {
    int numberOfTeams = Integer.MAX_VALUE;
    // Assign an array count of people in 5 Subjects
    int[] countArr = new int[5];
    for(int i=0;i<skills.length;i++){
       char subject = skills.charAt(i);
       if(subject=='p'){
            countArr[0]++;
       }else if(subject=='c'){
            countArr[1]++;
       }else if(subject=='m'){
            countArr[2]++;
       }else if(subject=='b'){
            countArr[3]++;
       }else if (subject=='z'){
            countArr[4]++;
       }else{ 
            throw new IllegalArgumentException("Invalid Input: " + subject); 
       }

    }
    // Iterate count array to find the Minimum Value
    for(int i=0;i<5;i++){
       if(countArr[i]<numberOfTeams){
          numberOfTeams = countArr[i];
       }
    }
    return numberOfTeams;
}

答案 1 :(得分:1)

在您的代码中,如果第二个if条件满足,则将i设置为0。这意味着迭代数量将等于可能的团队数量+1。因此,如果输入的冗长而可能的团队数量很多,则迭代次数会更多。这可能导致超时。

答案 2 :(得分:1)

这是您可以执行的另一种方法。它的工作原理是从技能串中删除每个主题并检查减少了其长度的程度。与其他方法一样,我们保持最小值。

static int differentTeams(String skills)
{
    int min = Integer.MAX_VALUE;
    for(String subj : "pcmbz".split(""))
    {
        String skillsRem = skills.replaceAll(subj, "");
        min = Math.min(skills.length() - skillsRem.length(), min);
        skills = skillsRem;
    }
    return min;
}

答案 3 :(得分:0)

Chegg website中,问题包括以下内容

  

该函数必须返回一个整数,该整数表示总数   满足以下条件的不同团队:    -一个小组由五个学生组成。    -每个学生都精通不同的科目。    -小组中的每个学生都不得加入任何其他小组。

对我来说,这听起来像是一个组合问题。换句话说,每个“ Z”是一个单独的学生,可以与许多其他“ P”组合以组成不同的团队。如果 是正确的解释,那么我相信正确的答案应该是(P数)*(C数)*(M数)*(B数)*(Z数) )。

这是Java 8的实现:

static int differentTeams(String skills) {
    Map<Character, Long> letterCounts = skills.chars().mapToObj(c -> (char) c)
            .collect(Collectors.groupingBy(
                    Function.identity(), Collectors.counting()
            ));

    //make sure there's at least one of each skill
    if (letterCounts.size() < 5) {
        return 0;
    }

    return letterCounts.values().stream()
            .reduce(1L, (a, b) -> a * b)
            .intValue();
}