#유형 : 트리, 자료구조

#난이도 : 프로그래머스 LEVEL 3

#입력을 우선순위큐를 사용하여 Y의 크기순, x는 작은순으로 정렬하면 된다. 우선순위큐를 사용해도 되고, 정렬기준을 통해 정렬을 해도 된다. 그러면 가장 앞에 루트노드가 올것이다. 그다음은 이진트리 조건에 따라 left, right를 정해서 트리를 완성하면 된다. 백준을 주로 풀어와서, 프로그래머스 문제는 좀 출력하기가 어색하다. 따라서 코드가 좀 복잡하게 보일 지라도, 기본 알고리즘은 간단하다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package programmers;
 
import java.util.ArrayList;
import java.util.PriorityQueue;
 
public class root {
    static No root;
    static ArrayList<Integer> re[];
    public static void main(String[] args) {
        int nodeinfo[][] = {{5,3},{11,5},{13,3},{3,5},{6,1},{1,3},{8,6},{7,2},{2,2}};
        int [][]answer = solution(nodeinfo);
        for(int i=0; i<2; i++) {
            for(int j=0; j<nodeinfo.length; j++)
                System.out.print(answer[i][j]+" " );
            System.out.println();
        }
    }
    public static int[][] solution(int[][] nodeinfo) {
        solve(nodeinfo);
        int[][] answer = new int[2][nodeinfo.length];
        for(int i=0; i<2; i++) {
                for(int j=0; j<nodeinfo.length; j++) {
                    answer[i][j] = re[i].get(j);
                }
        }
        return answer;
    }
    public static void solve(int[][] nodeinfo) {
//        int[][] answer = {};
        re = new ArrayList[2];
        for(int i=0; i<2; i++) {
                re[i]= new ArrayList<>();
        }
        PriorityQueue<Node> pq = new PriorityQueue<>();
        for(int i=0; i<nodeinfo.length; i++) {
                pq.add(new Node(nodeinfo[i][0], nodeinfo[i][1], i+1));
        }
        
        Node tmp = pq.poll();
        No newNo = new No(tmp.num, tmp.x);
        root = newNo;
        
        while(!pq.isEmpty()) {
                Node nd = pq.poll();
                No n = new No(nd.num, nd.x);
                
                find(root, n);
        }
        preorder(root);
        postorder(root);
    }
    private static void find(No r, No n) {
        // TODO Auto-generated method stub
        if(r.x > n.x && r.left != null) {
            find(r.left, n);
        }else if(r.x > n.x && r.left == null) {
            r.left = n;
        }else if(r.x < n.x && r.right != null) {
            find(r.right, n);
        }else {
            r.right=n;
        }
        
    }
    
    public static void preorder(No n) {
        if(n == null) {
            return;
        }
//        System.out.println(n.num);
        re[0].add(n.num);
        preorder(n.left);
        preorder(n.right);
    }
    public static void postorder(No n) {
        if(n == null)
            return;
        postorder(n.left);
        postorder(n.right);
        re[1].add(n.num);
    }
    
    public static class No{
        int num;
        int x;
        No left;
        No right;
        public No(int n, int x) {
            this.num=n;
            this.x=x;
            this.left=null;
            this.right=null;
        }
    }
    public static class Node implements Comparable<Node>{
        int x;
        int y;
        int num;
        public Node(int x, int y, int num) {
            this.x=x;
            this.y=y;
            this.num=num;
        }
        @Override
        public int compareTo(Node o) {
            // TODO Auto-generated method stub
            if(this.y < o.y)
                return 1;
            else if(this.y == o.y) {
                if(this.x > o.x)
                    return 1;
                else
                    return -1;
            }
            return -1;
        }
    }
}
 
cs

MYSQL의 DATE_FORMAT(값, 형식)을 사용하면 된다. 서브스트링을 써도 해결할 수 있다.

1
2
3
4
-- DATETIME에서 DATE로 형 변환
SELECT ANIMAL_ID, NAME, DATE_FORMAT(DATETIME'%Y-%m-%d') AS '날짜'
FROM ANIMAL_INS
ORDER BY ANIMAL_ID ASC`
cs

Join 문을 사용해서 병합한 다음, OUTS테이블의 DATETIME - INS테이블의 DATETIME을 뺀 값중 큰 값들을 내림차순으로 정렬하면 된다.

1
2
3
4
5
-- 오랜 기간 보호한 동물(2)
SELECT I.ANIMAL_ID, I.NAME
FROM ANIMAL_INS I LEFT JOIN ANIMAL_OUTS O ON I.ANIMAL_ID = O.ANIMAL_ID
ORDER BY O.DATETIME - I.DATETIME DESC
LIMIT 2
cs

특정한 값에 대하여 다른 값을 매칭시키기 위해 switch문 하고 비슷한 CASE를 사용하였다. 

CASE 

WHEN SEX_UPON_INTAKE like '%Neutered%' or  SEX_UPON_INTAKE like '%Spayed%' THEN 'O'

ELSE 'X' END 이런식으로 사용해주면 된다.

1
2
3
4
5
6
-- 중성화 여부 파악하기
SELECT ANIMAL_ID, NAME, CASE
WHEN SEX_UPON_INTAKE like '%Neutered%' or  SEX_UPON_INTAKE like '%Spayed%' THEN 'O'
ELSE 'X' END AS '중성화'
FROM ANIMAL_INS
 
cs

WHERE like '%문자%' 를 통해 해결할 수 있다.

1
2
3
4
5
-- 이름에 el이 들어가는 동물 찾기
SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE NAME like '%EL%' and ANIMAL_TYPE = 'Dog'
ORDER BY NAME ASC
cs

1. WHERE in 을 사용하는 방법

2. NAME = ' ' 으로 or 연결해서 해결하는 방법

1
2
3
4
5
6
7
8
9
-- 루시와 엘라찾기
SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE FROM ANIMAL_INS
WHERE Name in ('Lucy','Ella','Pickle','Rogan','Sabrina','Mitty')
ORDER BY ANIMAL_ID ASC
 
-- 루시와 엘라찾기
SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE FROM ANIMAL_INS
WHERE Name = 'Lucy' or Name ='Ella' or Name ='Pickle' or Name ='Rogan' or Name ='Sabrina' or Name ='Mitty'
ORDER BY ANIMAL_ID ASC
cs

** 1. 보호소에 들어올 당시에는 중성화되지 않았지만, 보호소를 나갈 당시에는 중성화된 동물의 아이디와 생물 종, 이름을 조회 

-> SELECT ANIMAL_OUTS.ANIMAL_ID, ANIMAL_OUTS.ANIMAL_TYPE, ANIMAL_OUTS.NAME

 

** 2. 병합을 위해, 조건에 있는 'ANIMAL_OUTS 테이블의 ANIMAL_ID ANIMAL_INS ANIMAL_ID의 외래 키입니다.'를 사용한다

-> FROM ANIMAL_INS LEFT JOIN ANIMAL_OUTS ON ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID ( JOIN, RIGHT JOIN가능)

 

** 3. 동물 보호소에 들어왔을때 중성화 되지 않았고, 보호소 나갈 당시에 중성화된 동물

-> WHERE I.SEX_UPON_INTAKE LIKE 'Intact%' AND (O.SEX_UPON_OUTCOME LIKE 'Neutered%' or O.SEX_UPON_OUTCOME LIKE 'Spayed%')

1
2
3
4
5
6
-- 보호소에서 중성화한 동물
SELECT O.ANIMAL_ID, O.ANIMAL_TYPE, O.NAME
FROM ANIMAL_OUTS O LEFT JOIN ANIMAL_INS I ON O.ANIMAL_ID = I.ANIMAL_ID
WHERE I.SEX_UPON_INTAKE LIKE 'Intact%' AND (O.SEX_UPON_OUTCOME LIKE 'Neutered%' or O.SEX_UPON_OUTCOME LIKE 'Spayed%')
 
 
cs

** 1. 입양 못간 동물 중, 가장 오래 보호소에 있었던 이름과 보호 시작일을 조회 -> SELECT ANIMAL_INS.NAME, ANIMAL_INS.DATETIME

 

** 2. 병합을 위해, 조건에 있는 'ANIMAL_OUTS 테이블의 ANIMAL_ID ANIMAL_INS ANIMAL_ID의 외래 키입니다.'를 사용한다 -> FROM ANIMAL_INS LEFT JOIN ANIMAL_OUTS ON ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID

 

** 3. 아직 입양을 못 간 동물 => ANIMAL_OUTS 의 NAME 또는 DATETIME 값이 null -> WHERE O.DATETIME is null

 

** 4. 보호 시작일 순으로 조회 + 3마리 -> ORDER BY I.DATETIME ASC LIMIT 3

1
2
3
4
5
6
-- 오랜 기간 보호한 동물(1)
SELECT I.NAME, I.DATETIME
FROM ANIMAL_INS I LEFT JOIN ANIMAL_OUTS O ON I.ANIMAL_ID = O.ANIMAL_ID
WHERE O.DATETIME is null
ORDER BY I.DATETIME ASC
LIMIT 3
cs

+ Recent posts