https://school.programmers.co.kr/learn/courses/30/lessons/49190
/**
* 좌표 xy를 가지는 Pair 객체가 필요하고
* map의 contains에 필요한 hashcode와 equlas를 오버리이딩 해서 재정의 해준다.
* 재정의를 안해줄 경우 주소값으로 비교하게 된다. ( 이 경우 equals가 의도대로 동작하지 않게 된다. )
* 대각선의 경우 문제의 그림처럼 진행할 경우 노드를 지나치지 않아 방 카운트를 하기 쉽지 않기 때문에
* 2배 스케일업 해서 노드를 지나도록 만들어야한다.
* key를 객체 value를 객체리스트로 만듦으로서 하나의 key는 최대 8개의 객체를 가진 리스트 value를 가질 수 있게 된다.
* 시간복잡도와 공간복잡도는 아직 지식이 없어 해당 코드가 어떤식으로 복잡도를 조율했는지 알 수 없다.
*/
public class Main {
public static void main(String[] args) {
System.out.println(solution(new int[]{6, 6, 6, 4, 4, 4, 2, 2, 2, 0, 0, 0, 1, 6, 5, 5, 3, 6, 0}));
}
static class Pair {
public int x;
public int y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
return Objects.hash(x,y);
}
@Override
public boolean equals(Object o) {
return this.x == ((Pair) o).x && this.y == ((Pair) o).y;
}
}
public static int solution(int[] arrows) {
// 변수 선언
int cnt = 0;
// 방향 관련 배열 선언
Pair pointHC = new Pair(0, 0);
int[] dx = { 0, 1, 1, 1, 0, -1, -1, -1 };
int[] dy = { 1, 1, 0, -1, -1, -1, 0, 1 };
// 방문 여부 관련 선언
// key = 시작 node의 hashcode, value = 연결된 node들의 hashcode
HashMap<Pair, ArrayList<Pair>> visitied = new HashMap<>();
// 로직 처리
for (int arrow : arrows) {
for (int i = 0; i <= 1; i++) { // 교차점 처리를 위한 스케일업(반복 2번)
// 이동 진행
Pair newPointHC = new Pair(pointHC.x + dx[arrow], pointHC.y + dy[arrow]);
// 처음 방문하는 경우 = map에 키값이 없는 경우
if (!visitied.containsKey(newPointHC)) {
// 리스트에 연결점 추가
visitied.put(newPointHC, makeEdgeList(pointHC));
if(visitied.get(pointHC) == null) { // 기존점도 없다면 업데이트
visitied.put(pointHC, makeEdgeList(newPointHC));
} else { // 기존점이 있다면 추가하기
visitied.get(pointHC).add(newPointHC);
}
// 재방문했고 간선을 처음 통과하는 경우
} else if (visitied.containsKey(newPointHC) && !(visitied.get(newPointHC).contains(pointHC))) {
visitied.get(newPointHC).add(pointHC);
visitied.get(pointHC).add(newPointHC);
cnt++;
}
// 이동 완료
pointHC = newPointHC;
}
}
return cnt;
}
// 밸류값에 넣기 위한 리스트 만들기
public static ArrayList<Pair> makeEdgeList(Pair pointHC) {
ArrayList<Pair> edge = new ArrayList<>();
edge.add(pointHC);
return edge;
}
}
나름 생각하며 코드를 짜봤지만 채점할 때마다 모든 케이스들을 틀려가지고 결국 접고 답을 봤다.
https://velog.io/@easycelsius/프로그래머스방의-개수
이 분의 게시글로 이해 될 때까지 공부했다.
덕분에 문제 해결을 위해 스케일업을 택한다는 유연한 사고와 이유를 알게되었고 Map안에 객체를 담아 관리하는 법을 어느정도 알게 된 것 같다. 정말 많은 공부가 됐다.
하지만 이 코드를 이해 했을 뿐 이런 문제를 만났을 때 스스로 이런 코드를 짤 수 있게 되려면 문제를 더 많이 풀어야만 가능할 것 같다.