[HashSet의 성격] 프로그래머스 방문 길이(실패분석 - HashSet의 Override 구현 )

byeol·2023년 4월 19일
0

접근

https://school.programmers.co.kr/learn/courses/30/lessons/49994#qna

이 문제는 HashSet의 hashCode()와 equals() 메서드를 이해하고 있었다면 쉽게 풀 수 있는 문제였습니다.
하지만 그 방법을 몰랐기 때문에 시간 내에 풀지 못했습니다.

여기서 구하고자 하는 것은 갔던 변인가를 구하는 것이기 때문에
(시작하는 x, 시작하는 y, 끝나는 x, 끝나는 y) 하나를 하나의 객체로 만들고

그 객체에서
시작하는 x = 끝나는 x , 시작하는 y=끝나는 y인 경우에는 중복된 값으로 인식하여
Set에 들어오지 못하게 하는 것입니다.

여기서 Set의 메커니즘을 알아야합니다.
Set은 어떻게 중복된 값을 들어오지 못하게 하는지를 보면 두 개의 메서드가 이를 가능하게 만들어 줍니다.

  1. 처음에 Object.hashCode()
    객체 번지값 혹은 주소값을 받아서 현재 HashSet에 있는 자료들 중에 같은 객체 번지값을 가진 자료가 있는지를 탐색합니다.
    만약에 없다면 그대로 중복되지 않는다고 판단하여 add 메서드를 통해 추가합니다.
  2. 하지만 같은 번지나 주소값이 있다면 equals() 메서드를 통해서 한번더 확인하는 절차를 가집니다.

문제는 위 절차가 객체를 만들어서 넣는 경우에는 제대로 작동하지 않는다는 것입니다. 따라서 두 개의 메소드를 Override해서 커스텀해야 합니다.

 static class XY{
        int sx;
        int sy;
        int ex;
        int ey;
        public XY(int sx, int sy, int ex, int ey){
            this.sx=sx;
            this.sy=sy;
            this.ex=ex;
            this.ey=ey;
        }
        }
   XY xy1 = new XY(1,2,3,4);
   XY xy2 = new XY(1,2,3,4);
   System.out.println(xy1.hashCode());
   System.out.println(xy2.hashCode());
   System.out.println(xy1.equals(xy2));

위 결과를 보면 당연히 다른 두 객체를 주소값이 다르게 나오지만 값이 같은 경우에도 false가 나옵니다.

따라서 같은 것으로 인식하게 하기 위해서
equals 메서드까지 도달하도록 해야하기 때문에
1. 저장된 값이 같은 경우 hashCode()의 return값이 같게 나오도록 해서
2. equals에 도달하도록 하는 과정이 필요합니다.
또한 위에서 언급한 시작하는 x = 끝나는 x , 시작하는 y=끝나는 y인 경우에는 중복된 값으로 인식하도록 equals에 조건문을 설정합니다.

풀이

import java.util.*;

class Solution {
    
    static int[] x={0,0,1,-1};
    static int[] y={1,-1,0,0};
    static List<Character> direct=List.of('U','D','R','L');;
    
    
    static class XY{
        int sx;
        int sy;
        int ex;
        int ey;
        public XY(int sx, int sy, int ex, int ey){
            this.sx=sx;
            this.sy=sy;
            this.ex=ex;
            this.ey=ey;
        }
        
        @Override
        public int hashCode() {
            return sx+sy+ex+ey;
        }
        
        @Override
        public boolean equals(Object obj){
            if(obj instanceof XY){
                //출발위치와 끝나는 위치가 같은 변
                if (sx==((XY)obj).sx &&sy==((XY)obj).sy &&
                      ex==((XY)obj).ex &&ey==((XY)obj).ey)
                    return true;
                // 출발위치와 끝나는 위치가 다르나 같은 변
                else if(sx==((XY)obj).ex &&sy==((XY)obj).ey &&
                      ex==((XY)obj).sx &&ey==((XY)obj).sy)
                    return true;
                }
            else 
                return false;
            
            return false;
        }
        
           
    }
    
    public int solution(String dirs) {
       
        
        Set<XY> set = new HashSet<>();
        
        int startX =0;
        int startY =0;
        
        for(char dir : dirs.toCharArray()){
            int tx = startX + x[direct.indexOf(dir)];
            int ty = startY + y[direct.indexOf(dir)];
            // 맵의 범위를 벗어난 경우 continue
            if(tx>5 || tx <-5 || ty>5 || ty<-5) continue;
            
             //set에 넣기
            set.add(new XY(startX,startY,tx,ty));
            //출발 위치 초기화
            startX = tx;
            startY = ty;
            }
        
        int answer = set.size();
       
        
        return answer;
                
    }
}
profile
꾸준하게 Ready, Set, Go!

0개의 댓글