Алгоритм для решения максимальных классов, посещаемых студентом - PullRequest
0 голосов
/ 12 февраля 2019

Алго спросил в одном из топовых интервью компании, я не могу найти выполнимое решение.Нужен совет специалиста.Предположим, что студент хочет посещать максимальное количество уроков в коллаже за день. Ниже приводятся подробности: указывается имя субъекта, время начала и время окончания урока.Входные данные будут

    **SUBJECT START_TIME END_TIME**
    Maths 16:00 18:00
    ComputerScience 12:00 13:00 
    Physics 12:30 14:00
    Chemistry 14:00 16:30

Выходными данными будет количество классов, которые студент может посещать.результат равен 2, студент может посещать 2 класса максимум согласно вышеуказанным данным, т.е. ComputerScience и либо по математике или химии.ниже мое решение, но я не получаю правильный ответ:

private void getMaxClass(String input) {

                Map<String, Long> classTime = new LinkedHashMap<>();
                Map<String, List<String>> timeMap = new LinkedHashMap<>();
                String [] split = input.split(" ");
                String subject = split[0];
                String StartTime = split[1];
                String endTime = split[2];
                List<String> lvalue = new ArrayList<>();
                lvalue.add(StartTime); lvalue.add(endTime);
                timeMap.put(subject, lvalue);
                long difference = FineDifferenceInTime(StartTime, endTime);
                classTime.put(subject, difference);
                int count =0;
                Date date1 = null;
                Date date2 = null;
                Map<String, Long> sortedByValueDesc = 
                classTime .entrySet() .stream() 
                .sorted(Map.Entry.<String, Long> comparingByValue())
                .collect( Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
                for (Map.Entry<String, Long> entry : sortedByValueDesc.entrySet()) {
                String sub = entry.getKey();
                List<String> startEnd = timeMap.get(sub);
                Date dateBefore = null;
                Date dateAfter = null;
                SimpleDateFormat format = new SimpleDateFormat("HH:mm");
                try {
                    dateBefore = format.parse(startEnd.get(0));
                    dateAfter = format.parse(startEnd.get(1));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if(count ==0){
                    count++;
                try {
                    date1 = format.parse(startEnd.get(0));
                    date2 = format.parse(startEnd.get(1));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                }
                if(dateBefore.after(date1) && dateBefore.before(date2)){
                    timeMap.remove(sub);
                }
            }
            System.out.println(timeMap.size());
}

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Это известно в литературе как Проблема планирования интервалов .Есть много способов ее решить, но так как она NP-завершена (так как есть полиномиальное сокращение от VC) , вам обязательно нужно изучить все комбинации.

Жадные алгоритмысуществуют (как ваше и решение @PriyankaDeshmukh), но они не гарантируют вам точное решение для всех случаев проблемы.

Решение ниже представляет собой простой поиск по дереву: на каждом уровне мырешить, брать ли мы данный курс или нет, и перейти к следующему курсу.

Вы также можете реализовать динамическое программирование.

Здесь оченьхорошее сообщение в блоге о решениях Интервальное планирование Проблема.

decision tree


Я смоделировал студенческий класс следующим образом:

class StudentClass {
    public int _start;
    public int _end;
    public String _name;
    public StudentClass(String name, int start, int end) {
        _name = name;
        _start = start;
        _end = end;
    }
    public boolean overlapsWith(StudentClass other) {
        return _start < other._end && _end > other._start;
    }
    public String toString() {
        return "[" + _start + " - " + _end + "] " + _name;
    }
}

Существуют классы, представляющие время дня, но их синтаксис / создание экземпляров немного раздражает / многословно - не стесняйтесь улучшать этот ответ!Моя Java также очень ржавая, поэтому не стесняйтесь исправлять меня: -)


Класс Schedule имеет getMaxSchedule(), который возвращает решение проблемы - какое максимальное количество классов aстудент может взять, чтобы ни один из них не перекрывался?

Есть несколько способов оптимизировать его, но я оставил его как есть, так как считаю, что его легче понять.

public class Schedule {

    List<StudentClass> _classes = new LinkedList<>();

    public void addClass(String name, int startTime, int endTime) {
        _classes.add(new StudentClass(name, startTime, endTime));
    }

    private int getMaxSchedule(int index, Collection<StudentClass> selected) {
        // check if we reached the end of the array
        if (index >= _classes.size()) {
            return 0;
        }

        StudentClass current = _classes.get(index);

        // check if taking this class doesn't conflict with the
        // previously-selected set of classes
        boolean canTakeThisClass = true;
        for (StudentClass other : selected) {
            if (current.overlapsWith(other)) {
                canTakeThisClass = false;
                break;
            }
        }

        // check best schedule if we don't take this class
        int best = getMaxSchedule(index + 1, selected);

        // check best schedule if we take this class (if such is possible)
        if (canTakeThisClass) {
            selected.add(current);
            best = Math.max(best, 1 + getMaxSchedule(index + 1, selected));
            selected.remove(current);
        }

        return best;
    }

    public int getMaxSchedule() {
        Collection<StudentClass> selected = new ArrayList<>();
        return getMaxSchedule(0, selected);
    }
}

Вы можете увидеть результат 3 для вашей конкретной проблемы с помощью следующего:

public static void main(String[] args) {
    Schedule s = new Schedule();
    s.addClass("Maths", 1600, 1800);
    s.addClass("Computer Science", 1200, 1300);
    s.addClass("Physics", 1230, 1400);
    s.addClass("Chemistry", 1400, 1630);
    System.out.println("maximum classes: " + s.getMaxSchedule());
}
0 голосов
/ 18 февраля 2019

Я попробовал это с Python.Это дает правильный вывод.Я отсортировал его по времени начала урока.

sorted_by_start = [{'sub': 'ComputerScience', 'start': '12:00', 'end': '13:00', 
'duration': 60}, {'sub': 'Physics', 'start': '12:30', 'end': '14:00', 'duration': 
90}, {'sub': 'Chemistry', 'start': '14:00', 'end': '16:30', 'duration': 150}, 
{'sub': 'Maths', 'start': '16:00', 'end': '18:00', 'duration': 120}]

possible_sub = set()

for a, b in itertools.combinations(sorted_by_start, 2):
    strt_tme = datetime.datetime.strptime(a["end"], '%H:%M')
    end_tme = datetime.datetime.strptime(b["start"], '%H:%M')
      if(strt_tme <= end_tme) :
        possible_sub.add((a["sub"],b["sub"]))

print("A student can attend these combinations of subject classes:",possible_sub)
print("Maximum classes student can attend in a day is: ",max(map(len,possible_sub)))

Здесь часть уловки решает, сколько комбинаций вы можете сделать.Итак, вы можете сделать это, добавив дополнительный цикл for в диапазоне от 2 до длины sorted_list и передав i в комбинации (sorted_list, i), например так:

Ouput is:

A student can attend these combinations of subject classes:  {('Physics', 'Maths'), ('Physics', 'Chemistry'), ('ComputerScience', 'Chemistry'), ('Compu
terScience', 'Maths')}
Maximum classes student can attend in a day is:  2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...