문제 풀기/C#

115. 호텔 대실(Tuple ,TimeSpan)

kagan-draca 2025. 6. 2. 18:01

 

기본 틀 : 

 

using System;

public class Solution {
    public int solution(string[,] book_time) {
        int answer = 0;
        return answer;
    }
}

 

처음 문제를 보고 '어떤 자료형을 선택해야 하지?' 라는 생각이 많이 들었다.

 

처음에는 

 

Dictionary<TimeSpan, List<TimeSpan>> dict = new Dicitionary<TimeSpan, List<TimeSpan>>();

 

으로 dictionary에 key를 입실 시간, value를 퇴실 시간들로 저장해야 하나 많은 고민을 했다.

 

TimeSpan은 C# 라이브러리의 자료형으로

 

https://kagan-draca.tistory.com/440

 

96. 주차 요금 계산(TimeSpan 자료형)

using System;public class Solution { public int[] solution(int[] fees, string[] records) { int[] answer = new int[] {}; return answer; }} 나름 재미있고 유익한 문제를 풀었다. 자동차 번호에 따른 입차, 출차 시간을 저장할 필

kagan-draca.tistory.com

 

위 문제에서 처음 접할 수 있었다.

 

그렇게 자료형을 만들고

 

dict = dict.OrderBy(X => X.Key).ToDictionary(X => X.Key, X=> X.Value);

 

로 dictionary를 정렬 후 필요한 방의 개수를 구하고자 시도했다.

 

하지만, 이때부터 dictionary는 문제가 존재하기 시작했다.

 

1. 입실 확인을 만드는 과정에서 이전 입실 전체 조회

(사용한 방을 다시 사용할 수 있는지 확인하기 위해서)

 

2. Key에 따른 Value가 여러 개

 

위 사항들을 종합할 경우 3중 for문을 작성해야 하는 문제가 발생했기 때문이다.

 

그래서, 다시 자료형을 생각해 본 결과

 

        List<(TimeSpan checkIn, TimeSpan checkOut)> timeList = new List<(TimeSpan checkIn, TimeSpan checkOut)>();

 

로 List와 Tuple을 사용해 입실과 퇴실 시간을 저장하면 된겠다는 판단을 했다.

 

(다행이 이전 문제처럼 C# 7.0 버전 이상 문제로 Tuple<TimeSpan, TimeSpan>으로 사용할 필요 없어서 편했다.)

 

그래서,

 

        for(int i = 0; i < book_time.GetLength(0); i++)
        {
            TimeSpan checkIn = TimeSpan.Parse(book_time[i, 0]);
            // 퇴실 시간에 청소 시간 + 10분 하기
            TimeSpan checkOut = TimeSpan.Parse(book_time[i, 1]) + TimeSpan.FromMinutes(10);
            timeList.Add((checkIn, checkOut));
        }

 

으로 입실 시간과 퇴실 시간(+10된 시간)을 저장한 후

 

        timeList = timeList.OrderBy(X=> X.checkIn).ToList();

 

입실 시간을 기준으로 list를 정렬해줬다.

 

그 다음으로 핵심적인 입실, 퇴실에 따른 방을 구하는 코드인데

 

        foreach((TimeSpan checkIn, TimeSpan checkOut) val in timeList)
        {
            // FindIndex는 해당 조건에 부합하는 앞 결과 index를 제공(없으면 -1 제공)
            // checkIn할 앞 선 시간 checkOut이 없었다면 방을 생성
            // checkOut 한 기록이 있으면 해당 방에 배정
            // (입실 시간으로 timeList가 정렬 돼 있기 때문에 가능)
            int room = roomList.FindIndex(element => element <= val.checkIn);
            if(room == -1) roomList.Add(val.checkOut);
            else roomList[room] = val.checkOut;
        }

 

timeList가 정렬된 상태이기 때문에 무조건 FindIndex의 결과는 해당 checkIn 앞 checkOut이 나올 수 밖에 없게 된다.

 

만약, checkOut이 없으면 FindIndex는 -1을 제공하게 될 것이고 방을 새로 만들어주면 된다.

 

전체 코드 :

 

using System;
using System.Linq;
using System.Collections.Generic;

public class Solution 
{
    public int solution(string[,] book_time) 
    {
        List<(TimeSpan checkIn, TimeSpan checkOut)> timeList = new List<(TimeSpan checkIn, TimeSpan checkOut)>();
        
        for(int i = 0; i < book_time.GetLength(0); i++)
        {
            TimeSpan checkIn = TimeSpan.Parse(book_time[i, 0]), checkOut = TimeSpan.Parse(book_time[i, 1]) + TimeSpan.FromMinutes(10);
            timeList.Add((checkIn, checkOut));
        }
        
        timeList = timeList.OrderBy(X=> X.checkIn).ToList();
        
        List<TimeSpan> roomList = new List<TimeSpan>();
        
        foreach((TimeSpan checkIn, TimeSpan checkOut) val in timeList)
        {
            int room = roomList.FindIndex(element => element <= val.checkIn);
            if(room == -1) roomList.Add(val.checkOut);
            else roomList[room] = val.checkOut;
        }
        
        return roomList.Count;
    }
}