[Programmers] 체육복

ds_chanin

·

2019. 10. 1. 01:56


본 게시글은 PC 환경에서 보기 편하도록 설정이 되어 있습니다.

체육복

탐욕법(Greedy)으로 분류 되어 있는 문제입니다.

학생들의 체육복 보유 여부와 빌려줄 수 있는지를 빠르게 계산하는 것이 문제의 핵심이었던 것 같습니다.

저는 이를 int[] studentStatus 를 이용하여 -1, 0, 1로 각각 나타내었습니다.

풀이 스타일

Java와 같은 객체지향 언어를 이용하여 알고리즘을 푼다면 객체지향스럽게 알고리즘을 풀어야 한다고 생각합니다.

단순한 알고리즘 풀이는 가독성은 당연히 떨어지고, Java를 쓰는 이유가 퇴색되는 것 같습니다.

따라서, Java를 이용해서 문제를 푸신다면 객체가 해야할 행동으로 문제를 풀 수 있도록 하시는 것을 추천드립니다.

Student 객체는 체육복을 빌려야하는지 알려주어야하고, 체육복을 빌려줄수 있는 상황인지 알려줄 수 있어야합니다.

따라서 각 객체는 식별자인 index.

체육복을 잃어버렸는지의 여부 값인 lost

체육복을 빌려줄 수 있는지의 여부값인 lendable 을 멤버변수로 가지고 있습니다.

코드

import java.util.ArrayList;
import java.util.List;

class Solution {
    public int solution(int n, int[] lost, int[] reserve) {

        int[] studentStatus = new int[n + 1];

        makeStudentStatus(studentStatus, lost, reserve);

        List<Student> students = new ArrayList<>();

        makeStudents(students, n, studentStatus);

        lendEachOther(students);

        return (int) students.stream()
                .filter(Student::hasSportsKit)
                .count();
    }

    private void makeStudentStatus(int[] studentStatus, int[] lost, int[] reserve) {
        for (int index : lost) {
            studentStatus[index]--;
        }
        for (int index : reserve) {
            studentStatus[index]++;
        }
    }


    private void makeStudents(List<Student> students, int n, int[] studentStatus) {
        for (int i = 1; i <= n; i++) {
            Student student = makeStudent(i, studentStatus[i]);
            students.add(student);
        }
    }

    private Student makeStudent(int index, int studentStatus) {
        if (studentStatus == -1) {
            return Student.makeLostStudent(index);
        }
        if (studentStatus == 0) {
            return Student.makeNormalStudent(index);
        }
        return Student.makeReserveStudent(index);
    }

    private void lendEachOther(List<Student> students) {
        for (int i = 0; i < students.size() - 1; i++) {
            Student producer = students.get(i);
            Student consumer = students.get(i + 1);
            producer.lendTo(consumer);
            consumer.lendTo(producer);
        }
    }

}

class Student {
    private Integer index;
    private boolean lost;
    private boolean lendable;

    public Student(Integer index, boolean lost, boolean lendable) {
        this.index = index;
        this.lendable = lendable;
        this.lost = lost;
    }

    public static Student makeLostStudent(int index) {
        return new Student(index, true, false);
    }

    public static Student makeReserveStudent(int index) {
        return new Student(index, false, true);
    }

    public static Student makeNormalStudent(int index) {
        return new Student(index, false, false);
    }

    public void lendTo(Student student) {
        if (!canLendable()) {
            return;
        }
        if (student.needLend()) {
            student.lend();
            this.lendable = false;
        }
    }

    private void lend() {
        this.lost = false;
    }

    public boolean hasSportsKit() {
        return !this.lost;
    }

    private boolean needLend() {
        return this.lost;
    }

    private boolean canLendable() {
        return this.lendable;
    }

}

'스터디 > 알고리즘' 카테고리의 다른 글

[백준] 블랙잭  (0) 2019.10.10
[Programmers] 프린터  (0) 2019.10.02
[Programmers] 베스트 앨범  (0) 2019.09.29
[Programmers] 가장 먼 노드  (0) 2019.09.29
[Programmers] 여행경로  (0) 2019.09.27