Post

[BaekJoon] #1764 - 듣보잡 [Java][C++]

[BaekJoon] #1764 - 듣보잡 [Java][C++]

문제 링크


1. 아이디어

듣도 못한 사람의 명단과 보도 못한 사람의 명단에 모두 포함된 사람의 명단을 사전 순으로 출력하는 문제로 두 집합의 교집합을 구하면 되는 간단한 문제다.


2. 복잡도

접근시간공간
풀이$O(N \log N + M)$$O(N + M)$

($N$ = 입력값 n, $M$ = 입력값 m, $K$ = 교집합의 크기. C++는 두 집합을 std::unordered_set에 담고 교집합만 std::set에 정렬해 시간 $O(N + M + K \log K)$)


3. 코드

풀이 [Java][C++]

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
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st = new StringTokenizer(br.readLine());

        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());

        Set<String> tset = new TreeSet<>();
        while (n-- > 0) {
            tset.add(br.readLine());
        }

        Set<String> hset = new HashSet<>();
        while (m-- > 0) {
            hset.add(br.readLine());
        }

        tset.retainAll(hset);

        sb.append(tset.size()).append("\n");
        for (String s : tset) {
            sb.append(s).append("\n");
        }

        System.out.println(sb);
    }
}

듣도 못한 사람은 TreeSet으로 보도 못한 사람은 HashSet으로 저장한 후 retainAll 메서드로 두 집합의 교집합을 구했다. TreeSet은 이미 정렬된 채로 저장하기 때문에 순회하면서 출력만 하면 된다.

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
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    unordered_set<string> st1;
    while (n--) {
        string s;
        cin >> s;
        st1.insert(s);
    }

    unordered_set<string> st2;
    while (m--) {
        string s;
        cin >> s;
        st2.insert(s);
    }

    set<string> inter;
    if (st1.size() > st2.size()) swap(st1, st2);

    for (auto& s : st1) {
        if (st2.count(s)) inter.insert(s);
    }

    cout << inter.size() << '\n';
    for (auto& s : inter) {
        cout << s << '\n';
    }
}

std::set으로 교집합을 선언하고 한쪽 집합을 순회하면서 해당 원소가 반대쪽 집합에도 포함되어 있으면 교집합에 넣는 방식으로 구현했다. 이때 성능은 순회를 하는 쪽이 좌우하므로 더 작은 집합을 순회하도록 std::swap 함수를 활용했다.


This post is licensed under CC BY 4.0 by the author.