코딩테스트/백준

[Java] 백준 19583번 - 싸이버개강총회

곰돌이볼 2023. 3. 9. 14:53
  • 문제
    • 개강총회 출석부 관리
      • 입장과 퇴장이 전부 확인 된 학생 수 구하기

 

  • 조건
    • 00:00 ~ 개강총회 시작시점에 채팅 기록이 있는 학생 → 입장 확인
    • 개강총회 종료 시점 ~ 스트리밍 종료 시점에 채팅 기록이 있는 학생 → 퇴장 확인
    • 스트리밍 종료 시점 이후 채팅 기록은 인정 X
    • S : 개강총회 시작 시간
    • E : 개강총회 종료 시간
    • Q : 스트리밍 종료 시간
    • 시간 형태 : HH:MM

 

  • 로직 1)
    • 입력이 있을 때까지 반복
      • 00:00 ~ S 사이 시간에 채팅을 남긴 학생을 ArrayList인 startStudent에 추가하기
      • E ~ Q 사이 시간에 채팅을 친 학생 중 start에 포함된 학생이면 구하려는 학생수 count 수 증가하기
    • count 출력하기
package backjoon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 입력받기
        String[] str = br.readLine().split(" ");

        // 개강총회 시작시간
        int[] start = new int[2];
        start[0] = Integer.valueOf(str[0].split(":")[0]);
        start[1] = Integer.valueOf(str[0].split(":")[1]);

        // 개강총회 종료시간
        int[] finsih = new int[2];
        finsih[0] = Integer.valueOf(str[1].split(":")[0]);
        finsih[1] = Integer.valueOf(str[1].split(":")[1]);

        // 스트리밍 종료시간
        int[] streamingFinish = new int[2];
        streamingFinish[0] = Integer.valueOf(str[2].split(":")[0]);
        streamingFinish[1] = Integer.valueOf(str[2].split(":")[1]);

        List<String> startStudent = new ArrayList<>(); // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을
        int count = 0; // 최종 구하려는 학생수

        String tmp = "";
        while((tmp = br.readLine()) != null) {
            str = tmp.split(" ");
            int hour = Integer.valueOf(str[0].split(":")[0]);
            int minute = Integer.valueOf(str[0].split(":")[1]);

            // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을 ArrayList인 start에 추가하기
            if(findTime(start[0], start[1], hour, minute) <= 1) {
                startStudent.add(str[1]);
            } else if(finishCheck(finsih, streamingFinish, hour, minute)) {
                // finish ~ streamingFinish 사이 시간에 채팅을 친 학생 중 start에 포함된 학생이면 구하려는 학생수 count 수 증가하기
                String name = str[1];
                if(startStudent.contains(name)) count++;
            }
        }

        System.out.println(count);
    }

    // 기준시간 이전, 포함, 이후 구분 메서드
    public static int findTime(int originHour, int originMinute, int hour, int minute) {
        // 기준시간 이전 : 0
        // 기준시간 포함 : 1
        // 기준시간 이후 : 2

        if(originHour == hour) {
            if(minute < originMinute) return 0;
            else if(originMinute == minute) return 1;
            else return 2;
        }
        else if(originHour < hour) return 2;
        else return 0;
    }

    // finish ~ streamingFinish 사이 시간에 채팅을 친 학생 중 start에 포함된 학생이면 true
    public static boolean finishCheck(int[] finish, int[] streamingFinish, int hour, int minute) {
        if(findTime(finish[0], finish[1], hour, minute) >= 1)
            if(findTime(streamingFinish[0], streamingFinish[1], hour, minute) <= 1) return true;

        return false;
    }
}

 

  • 결과
    • 시간초과 → 이유 : hour과 minute을 분리해서 그런 것 같음

 

 

  • 로직 2)
    • hour과 minute을 분리하지 말고 시간 비교하기
    • compareTo 메서드 이용하기
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 입력받기
        String[] time = br.readLine().split(" "); // 시간

        List<String> startStudent = new ArrayList<>(); // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을
        int count = 0; // 최종 구하려는 학생수

        String tmp = "";
        while((tmp = br.readLine()) != null) {
            String commentTime = tmp.split(" ")[0];
            String name = tmp.split(" ")[1];

            // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을 ArrayList인 start에 추가하기
            if(time[0].compareTo(commentTime) >= 0) {
                startStudent.add(name);
            } else if(commentTime.compareTo(time[1]) >= 0 && time[2].compareTo(commentTime) >= 0) {
                // finish ~ streamingFinish 사이 시간에 채팅을 친 학생 중 start에 포함된 학생이면 구하려는 학생수 count 수 증가하기
                if(startStudent.contains(name)) {
                    startStudent.remove(name);
                    count++;
                }
            }
        }

        System.out.println(count);
    }
}

 

  • 결과
    • 시간초과 → 이유 : finish ~ streamingFinish 사이의 시간일 때마다 입장 확인도 했는지 확인하는 로직
    • count 사용 시 중복된 댓글을 걸러내지 못함

 

  • 로직 3)
    • finish ~ streamingFinish 사이의 시간일 때 ArrayList 배열인 finishStudent에 name 추가하기
    • startStudent와 finishStudent에 공통된 name 추출하기
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 입력받기
        String[] time = br.readLine().split(" "); // 시간

        List<String> startStudent = new ArrayList<>(); // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을
        List<String> finishStudent = new ArrayList<>(); // finish ~ streamingFinish 사이 시간에 채팅을 남긴 학생을
        int count = 0; // 최종 구하려는 학생수

        String tmp = "";
        while((tmp = br.readLine()) != null) {
            String commentTime = tmp.split(" ")[0];
            String name = tmp.split(" ")[1];

            // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을 ArrayList인 start에 추가하기
            if(time[0].compareTo(commentTime) >= 0) {
                startStudent.add(name);
            } else if(commentTime.compareTo(time[1]) >= 0 && time[2].compareTo(commentTime) >= 0) {
                // finish ~ streamingFinish 사이 시간에 채팅을 친 학생 중 start에 포함된 학생이면 구하려는 학생수 count 수 증가하기
                if(startStudent.contains(name)) {
                    finishStudent.add(name);
                }
            }
        }

        startStudent.retainAll(finishStudent);
        System.out.println(startStudent.size());
    }
}

 

  • 결과
    • 시간초과 → 이유 : arrayList 사용

 

  • 로직 4)
    • ArrayList 대신 HashSet 사용
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 입력받기
        String[] time = br.readLine().split(" "); // 시간

        Set<String> startStudent = new HashSet<>(); // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을
        Set<String> finishStudent = new HashSet<>(); // finish ~ streamingFinish 사이 시간에 채팅을 남긴 학생을

        String tmp = "";
        while((tmp = br.readLine()) != null) {
            String commentTime = tmp.split(" ")[0];
            String name = tmp.split(" ")[1];

            // 00:00 ~ start 사이 시간에 채팅을 남긴 학생을 ArrayList인 start에 추가하기
            if(time[0].compareTo(commentTime) >= 0) {
                startStudent.add(name);
            } else if(commentTime.compareTo(time[1]) >= 0 && time[2].compareTo(commentTime) >= 0) {
                // finish ~ streamingFinish 사이 시간에 채팅을 친 학생 중 start에 포함된 학생이면 구하려는 학생수 count 수 증가하기
                if(startStudent.contains(name)) {
                    finishStudent.add(name);
                }
            }
        }

        startStudent.retainAll(finishStudent);
        System.out.println(startStudent.size());
    }
}

 

  • 결과