첫 줄에 n, 둘째 줄에 정수 n개(묶음 A), 셋째 줄에 m, 넷째 줄에 정수 m개(묶음 B)가 주어진다. 한 묶음 안에 같은 수가 여러 번 나올 수 있지만, 집합으로 볼 때는 한 번만 센다. 세 줄을 출력하라.
1. A와 B의 합집합(둘 중 하나에라도 있는 수)
2. A와 B의 교집합(둘 다에 있는 수)
3. A에서 B를 뺀 차집합(A에는 있고 B에는 없는 수)
줄마다 수를 한 번씩만, 작은 수부터 빈칸 하나로 띄워 출력한다. 해당하는 수가 없으면 "-" 하나를 출력한다.
입력
1 ≤ n, m ≤ 5,000, -2,000,000,000 ≤ 각 정수 ≤ 2,000,000,000
출력
세 줄(합집합, 교집합, 차집합)
예시 1 · stdin
7
10 9 2 100 -1 -20 3
5
9 100 -20 7 7
stdout
-20 -1 2 3 7 9 10 100
-20 9 100
-1 2 3 10
예시 2 · stdin
3
5 5 5
1
5
stdout
5
5
-
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
집합 연산을 부르는 이름이 언어마다 달라요. Python은 연산자 a | b·a & b·a - b, Java는 addAll·retainAll·removeAll, C#은 UnionWith·IntersectWith·ExceptWith예요. Java·C# 메서드는 원래 집합을 바꾸니 복사본에 해요. C++은 std::set_union·set_intersection·set_difference가 정렬된 범위를 받아서 std::set(늘 크기 순)과 잘 맞아요. JS·TS Set은 집합 연산이 오래 없어서(최근에야 union 등이 생겼어요) filter(x => b.has(x))로 많이 써요. 차례도 조심해요. Python set은 도는 차례가 크기 순이 아니라서 sorted가 필요하고, JS·TS의 sort()는 비교 함수를 안 주면 글자 순이라 10이 9보다 앞에 와요. sort((x, y) => x - y)로 써요. Java TreeSet·C# SortedSet은 늘 크기 순이에요. C에는 집합이 없어서 둘 다 정렬하고 겹친 값을 지운 뒤 앞에서부터 함께 훑어요(병합). 이때 qsort 비교 함수가 a - b를 돌려주면 ±20억끼리 빼다 int(약 ±21억)가 넘쳐 차례가 틀려요. (a > b) - (a < b)로 써요. 목록으로 차집합을 만들면([x for x in a if x not in b]) 겹친 값이 남는 것도 흔한 실수예요. 크레이콘은 사전()의 열쇠를 집합처럼 쓰고, 있나로 물으며, 열쇠목록을 정렬()해 잇기(" ")로 써요.
Pythonmain.py · 14 줄
input()a = set(map(int, input().split()))input()b = set(map(int, input().split()))def show(s): # 집합에는 차례가 없으니 출력 전에 크기 순으로 늘어놓는다 return " ".join(map(str, sorted(s))) if s else "-"print(show(a | b))print(show(a & b))print(show(a - b))
JavaScriptmain.js · 9 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const a = new Set(lines[1].trim().split(/\s+/).map(Number));const b = new Set(lines[3].trim().split(/\s+/).map(Number));// sort()만 쓰면 글자 순(10이 9보다 앞)이라 비교 함수를 준다const show = (s) => (s.size ? [...s].sort((x, y) => x - y).join(" ") : "-");const union = new Set([...a, ...b]);const inter = new Set([...a].filter((x) => b.has(x)));const diff = new Set([...a].filter((x) => !b.has(x)));console.log([show(union), show(inter), show(diff)].join("\n"));
TypeScriptmain.ts · 10 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const a = new Set<number>(lines[1].trim().split(/\s+/).map(Number));const b = new Set<number>(lines[3].trim().split(/\s+/).map(Number));// sort()만 쓰면 글자 순(10이 9보다 앞)이라 비교 함수를 준다const show = (s: Set<number>): string => (s.size ? [...s].sort((x, y) => x - y).join(" ") : "-");const union = new Set<number>([...a, ...b]);const inter = new Set<number>([...a].filter((x) => b.has(x)));const diff = new Set<number>([...a].filter((x) => !b.has(x)));console.log([show(union), show(inter), show(diff)].join("\n"));
JavaMain.java · 35 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.TreeSet;public class Main { static TreeSet<Integer> readSet(BufferedReader in) throws IOException { in.readLine(); TreeSet<Integer> s = new TreeSet<>(); for (String t : in.readLine().trim().split("\\s+")) s.add(Integer.parseInt(t)); return s; } static String show(TreeSet<Integer> s) { if (s.isEmpty()) return "-"; StringBuilder sb = new StringBuilder(); for (int x : s) sb.append(sb.length() > 0 ? " " : "").append(x); return sb.toString(); } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); // TreeSet은 늘 크기 순으로 돈다. addAll·retainAll·removeAll은 원래 집합을 바꾸니 복사해서 쓴다 TreeSet<Integer> a = readSet(in), b = readSet(in); TreeSet<Integer> union = new TreeSet<>(a); union.addAll(b); TreeSet<Integer> inter = new TreeSet<>(a); inter.retainAll(b); TreeSet<Integer> diff = new TreeSet<>(a); diff.removeAll(b); System.out.println(show(union)); System.out.println(show(inter)); System.out.println(show(diff)); }}
C#Main.cs · 30 줄
using System;using System.Collections.Generic;using System.Linq;class Program{ static SortedSet<int> ReadSet() { Console.ReadLine(); return new SortedSet<int>(Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse)); } static string Show(SortedSet<int> s) => s.Count == 0 ? "-" : string.Join(" ", s); static void Main() { // SortedSet은 늘 크기 순으로 돈다. UnionWith 등은 원래 집합을 바꾸니 복사해서 쓴다 var a = ReadSet(); var b = ReadSet(); var union = new SortedSet<int>(a); union.UnionWith(b); var inter = new SortedSet<int>(a); inter.IntersectWith(b); var diff = new SortedSet<int>(a); diff.ExceptWith(b); Console.WriteLine(Show(union)); Console.WriteLine(Show(inter)); Console.WriteLine(Show(diff)); }}
C++main.cpp · 34 줄
#include <algorithm>#include <iostream>#include <iterator>#include <set>#include <vector>std::set<int> read_set() { int n, x; std::cin >> n; std::set<int> s; for (int i = 0; i < n; i++) { std::cin >> x; s.insert(x); } return s;}void show(const std::vector<int>& v) { if (v.empty()) std::cout << "-"; for (std::size_t i = 0; i < v.size(); i++) std::cout << (i ? " " : "") << v[i]; std::cout << '\n';}int main() { // std::set은 크기 순이라 set_union 등에 바로 넘길 수 있다(정렬된 범위가 필요하다) std::set<int> a = read_set(), b = read_set(); std::vector<int> u, in, d; std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(u)); std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(in)); std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(d)); show(u); show(in); show(d);}
Cmain.c · 50 줄
#include <stdio.h>#include <stdlib.h>// a - b 를 돌려주면 ±20억끼리 빼서 int가 넘친다 — 크기만 비교한다static int cmp(const void *pa, const void *pb) { int a = *(const int *)pa, b = *(const int *)pb; return (a > b) - (a < b);}// 읽어서 정렬한 뒤 겹친 값을 지운다. 남은 개수를 돌려준다static int read_set(int *s) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &s[i]); qsort(s, n, sizeof s[0], cmp); int k = 0; for (int i = 0; i < n; i++) if (k == 0 || s[k - 1] != s[i]) s[k++] = s[i]; return k;}static void show(const int *s, int n) { if (n == 0) printf("-"); for (int i = 0; i < n; i++) printf(i ? " %d" : "%d", s[i]); printf("\n");}int main(void) { static int a[5000], b[5000], u[10000], in[5000], d[5000]; int n = read_set(a), m = read_set(b); int nu = 0, ni = 0, nd = 0, i = 0, j = 0; // 정렬된 두 목록을 앞에서부터 함께 훑는다(병합) while (i < n || j < m) { if (j == m || (i < n && a[i] < b[j])) { u[nu++] = a[i]; d[nd++] = a[i++]; } else if (i == n || b[j] < a[i]) { u[nu++] = b[j++]; } else { u[nu++] = a[i]; in[ni++] = a[i]; i++; j++; } } show(u, nu); show(in, ni); show(d, nd); return 0;}
Craykonmain.cray · 47 줄
// 사전의 열쇠를 집합처럼 쓴다(값은 아무거나)집합읽기(){ 콘솔.줄읽기(); s = 사전(); 각각 (x 에서 콘솔.수들읽기()) { s[x] = 참; } 돌려주기 s;}보이기(s){ 만약 (s.개수 == 0) { 돌려주기 "-"; } keys = s.열쇠목록; keys.정렬(); 돌려주기 keys.잇기(" ");}a = 집합읽기();b = 집합읽기();합 = 사전();교 = 사전();차 = 사전();각각 (x 에서 a.열쇠목록){ 합[x] = 참; 만약 (b.있나(x)) { 교[x] = 참; } 아니면 { 차[x] = 참; }}각각 (x 에서 b.열쇠목록){ 합[x] = 참;}콘솔.쓰기(보이기(합));콘솔.쓰기(보이기(교));콘솔.쓰기(보이기(차));