이 파트는 취이코전 풀이보다 재미니가 나음.

import java.util.*;
 
class Solution {
    // 배열 대신 Map을 사용하여 필요한 방 정보만 저장합니다.
    // Key: 이미 배정된 방, Value: 그 방 대신 가야 할 다음 방
    Map<Long, Long> parentMap = new HashMap<>();
 
    public long[] solution(long k, long[] room_numbers) {
        long[] answer = new long[room_numbers.length];
 
        for (int i = 0; i < room_numbers.length; i++) {
            long requestedRoom = room_numbers[i];
            long assignedRoom = find(requestedRoom);
            answer[i] = assignedRoom;
        }
 
        return answer;
    }
 
    /**
     * 지정된 방 번호(room)에 대해 배정 가능한 실제 방 번호를 찾습니다.
     * Union-Find 알고리즘의 'find' 연산과 경로 압축을 수행합니다.
     * @param room 원하는 방 번호
     * @return 배정 가능한 방 번호
     */
    private long find(long room) {
        // 1. 이 방이 Map에 없다면, 아직 비어있다는 의미입니다.
        if (!parentMap.containsKey(room)) {
            // 2. 이 방을 배정하고, 다음 요청자를 위해 (room + 1)을 가리키도록 설정합니다. (Union 연산)
            parentMap.put(room, room + 1);
            return room;
        }
 
        // 3. 이 방이 이미 차있다면, 이 방이 가리키는 다음 방으로 가서 빈 방을 찾습니다. (재귀 호출)
        long nextRoom = parentMap.get(room);
        long emptyRoom = find(nextRoom);
 
        // 4. 경로 압축: 현재 방이 최종적으로 찾은 빈 방을 직접 가리키도록 업데이트합니다.
        // 이렇게 하면 다음번에 이 방을 찾을 때 훨씬 빨라집니다.
        parentMap.put(room, emptyRoom);
        
        return emptyRoom;
    }
}
 
import java.util.*;
class Solution {
    public long[] solution(long k, long[] roomNumbers) {
        //k는 최대 1억, roomNumbers는 200,000개 최대
        //1~K 방번호 존재
        //이미 방이 배정되어있다면 그 방보다 번호가 크면서 빈곳중 번호가 젤 작은거
        
        DisjointSet disjointSet = new DisjointSet(k);
        List<Long> ansList = new ArrayList<>();
        for(long roomNumber : roomNumbers){
            long rootRoomNumber = disjointSet.find(roomNumber);
            
            if(rootRoomNumber != roomNumber){
                //지금 가져돈 루트를 방으로 배정하고 이 루트를 +1쪽으로 합친다.
                ansList.add(rootRoomNumber);
                disjointSet.union(rootRoomNumber, disjointSet.find(rootRoomNumber + 1));
                
            }else{
                ansList.add(rootRoomNumber);
                disjointSet.union(rootRoomNumber, disjointSet.find(rootRoomNumber + 1));
            }
        }
        long[] ans = new long[ansList.size()];
        for(int i=0 ; i<ans.length ; i++){
            ans[i] = ansList.get(i);
        }
        return ans;
    }
    
    class DisjointSet{
        List<Long> parents = new ArrayList<>();
        
        public DisjointSet(long n){
            for(long i=0 ; i<n ; i++){
                parents.add(i);
            }
        }
        
        public void union(long u, long v){
            long rootU = find(u);
            long rootV = find(v);
            
            if(rootU != rootV){
                parents.set(rootU, parents.get(rootV));
            }
        }
        
        public long find(long u){
            if(parents.get(u) == u){
                return u;
            }
            
            parents.set(u, find(parents.get(u)));
            return parents.get(u);
        }
    }
}