Lewis's Tech Keep
[프로그래머스] 입실 퇴실 - Java 본문
- 링크 : https://programmers.co.kr/learn/courses/30/lessons/86048?language=java
코딩테스트 연습 - 7주차
사회적 거리두기를 위해 회의실에 출입할 때 명부에 이름을 적어야 합니다. 입실과 퇴실이 동시에 이뤄지는 경우는 없으며, 입실 시각과 퇴실 시각은 따로 기록하지 않습니다. 오늘 회의실에는
programmers.co.kr
- 풀이
- 처음에 생각해야 할 부분이 무조건 만나는 경우를 생각하기 위해서는 worst case를 생각해야 한다.
이는 leave 의 조건이 충족하자마자 바로 나가는 경우이다.
떠날 수 있을 때 바로 떠나는 경우를 기준으로 생각하고 푼다면 답을 얻을 수 있다.
- 설정 부분
1. 들어온 사람이 중복되지 않으므로 enter length 길이가 들어온 사람 수이다.
2. 이를 이용해 map을 초기화
3. leave 배열 생성 (remove 가 많이 일어나고 search가 별로 없을 것 같아서 linkedlist로 선택)
4. room 배열 생성 (방에 들어왔다가 나갔다하는 배열 이 역시 add remove 가 많을 것 같아서 linkedlist로 선택)
- 로직 부분
1. enter 배열에서 room으로 방에 들어온 사람을 확인한다.
2. room에 2명 이상의 사람이 들어올 때 count 시작
3. ex. room : [1, 2] 이고 3이 방에 들어왔다고 할 때
기존에 있던 사람(1, 2) 에게는 현재 카운트 + 1, 현재 새로 들어온 사람(3)은 이전에 들어와 있던 사람 수(2명) 을 기록한다.
이를 마지막으로 들어왔을 때까지 해주면 된다.
- 코드
import java.util.*;
class Solution {
public int[] solution(int[] enter, int[] leave) {
Map<Integer, Integer> map = new HashMap<>();
for (int i=1; i<=enter.length; i++) {
map.put(i, 0);
}
List<Integer> lArr = new LinkedList<>();
for (int i=0; i<leave.length; i++) {
lArr.add(leave[i]);
}
List<Integer> room = new LinkedList<>();
for (int i=0; i < enter.length; i++) {
int a = enter[i];
room.add(a);
if (room.size() > 1) {
for (int j=0; j < room.size(); j++) {
int peopleNum = room.get(j);
map.put(peopleNum, map.getOrDefault(peopleNum, 0) + 1);
}
}
map.put(a, room.size()-1); // 나 자신을 제외한 만난 사람 수
while(lArr.size() > 0 && room.contains(lArr.get(0))) {
room.remove(lArr.get(0));
lArr.remove(0);
}
}
int[] answer = new int[map.size()];
int i = 0;
for (int key : map.keySet()) {
answer[i++] = map.get(key);
}
return answer;
}
}
- 처음에 틀렸던 풀이
- 나름 고민했는데 틀렸지만 기록해 두려고 한다.
- 시도한 부분
- 방에서 나가는 시점을 기준으로 반드시 그 사람이 있었던 경우를 2가지로 나누었다.
a가 반드시 b를 만나는 경우
1. b가 a보다 늦게 들어왔지만 b가 먼저 나갔다.
2. b가 a보다 늦게 들어왔고 b가 늦게 나갔지만 b보다 더 늦게 들어온 c가 먼저 나갔다.
(더 늦게 들어온 사람이 더 늦게 나갔다면 a를 만났는 지 확신할 수 없음)
- 문제점
- 해당 코드가 내 생각에는 O(N^4)까지 갈 수 있는 코드였다. 이는 시간 초과를 이끄는 코드였고 해당 코드는 실패했다.
- 시간 복잡도를 고려한 풀이가 생각나지 않아서 시도한 코드였지만 이 방법을 기록 해 놓고 싶었다.
- 실패 코드
import java.util.*;
class Solution {
public int[] solution(int[] enter, int[] leave) {
Map<Integer, Integer> map = new HashMap<>();
for (int i=1; i<=enter.length; i++) {
map.put(i, 0);
}
for (int i=0; i<enter.length; i++) {
for (int j=i+1; j<enter.length; j++) {
int a = enter[i];
int b = enter[j];
int eaIdx = i;
int laIdx = getLeaveIndex(a, leave);
int ebIdx = j;
int lbIdx = getLeaveIndex(b, leave);
if (laIdx - lbIdx > 0) {
// b가 a보다 늦게 들어왔는데 b가 먼저 나감
map.put(a, map.getOrDefault(a, 0) + 1);
map.put(b, map.getOrDefault(b, 0) + 1);
continue;
}
// b가 a보다 늦게 들어오고 b가 늦게 나갔지만 b보다 더 늦게 들어온 c가 먼저 나감
for (int k=j+1; k<enter.length; k++) {
int c = enter[k];
int lcIdx = getLeaveIndex(c, leave);
if (lcIdx < laIdx) {
lbIdx = lcIdx;
break;
}
}
if (laIdx - lbIdx > 0) {
// b가 a보다 늦게 들어왔는데 b가 먼저 나감
map.put(a, map.getOrDefault(a, 0) + 1);
map.put(b, map.getOrDefault(b, 0) + 1);
continue;
}
}
}
int[] answer = new int[map.size()];
int i = 0;
for (int key : map.keySet()) {
answer[i++] = map.get(key);
}
return answer;
}
public int getLeaveIndex(int num, int[] leave) {
for (int i=0; i<leave.length; i++) {
if (leave[i] == num) {
return i;
}
}
return -1;
}
}
'Java > 알고리즘' 카테고리의 다른 글
[프로그래머스] 징검다리 건너기 - Java (0) | 2021.10.01 |
---|---|
[프로그래머스] 금과 은 운반하기 - JAVA (0) | 2021.09.27 |
[BOJ] 비트 우정지수 - JAVA (0) | 2021.09.13 |
[프로그래머스] 복서 정렬하기 - JAVA (0) | 2021.09.13 |
[프로그래머스] 모음 사전 - JAVA (0) | 2021.09.06 |