티어 : Silver 4 시간 제한 : 2 초 메모리 제한 : 256 MB 알고리즘 분류 : 자료 구조, 정렬, 이분 탐색, 해시를 사용한 집합과 맵
문제
연종이는 엄청난 기억력을 가지고 있다. 그래서 하루 동안 본 정수들을 모두 기억 할 수 있다. 하지만 이를 믿을 수 없는 동규는 그의 기억력을 시험해 보기로 한다. 동규는 연종을 따라 다니며, 연종이 하루 동안 본 정수들을 모두 ‘수첩1’에 적어 놓았다. 그것을 바탕으로 그가 진짜 암기왕인지 알아보기 위해, 동규는 연종에게 M개의 질문을 던졌다. 질문의 내용은 “X라는 정수를 오늘 본 적이 있는가?” 이다. 연종은 막힘없이 모두 대답을 했고, 동규는 연종이 봤다고 주장하는 수 들을 ‘수첩2’에 적어 두었다. 집에 돌아온 동규는 답이 맞는지 확인하려 하지만, 연종을 따라다니느라 너무 힘들어서 여러분에게 도움을 요청했다. 동규를 도와주기 위해 ‘수첩2’에 적혀있는 순서대로, 각각의 수에 대하여, ‘수첩1’에 있으면 1을, 없으면 0을 출력하는 프로그램을 작성해보자.
입력
첫째 줄에 테스트케이스의 개수 T가 들어온다. 다음 줄에는 ‘수첩 1’에 적어 놓은 정수의 개수 N(1 ≤ N ≤ 1,000,000)이 입력으로 들어온다. 그 다음 줄에 ‘수첩 1’에 적혀 있는 정수들이 N개 들어온다. 그 다음 줄에는 ‘수첩 2’에 적어 놓은 정수의 개수 M(1 ≤ M ≤ 1,000,000) 이 주어지고, 다음 줄에 ‘수첩 2’에 적어 놓은 정수들이 입력으로 M개 들어온다. 모든 정수들의 범위는 int 로 한다.
출력
‘수첩2’에 적혀있는 M개의 숫자 순서대로, ‘수첩1’에 있으면 1을, 없으면 0을 출력한다.
예제 입출력
Algorithm
1. bisect 이용 2. 첫 번째 수첩 정렬 3. bisect_left와 bisect_right가 같으면 0, 다르면 1 출력
Code
import sys
from bisect import bisect_left, bisect_right
input = sys.stdin.readline
# 입력
T = int(input())
for _ in range(T):
_ = input()
array_n = list(map(int, input().split()))
_ = input()
array_m = list(map(int, input().split()))
# array_n 정렬
array_n.sort()
for i in array_m:
# left와 right가 다르면 1, 같으면 0 출력
if bisect_left(array_n, i) == bisect_right(array_n, i):
print(0)
else:
print(1)
티어 : Silver 4 시간 제한 : 1 초 메모리 제한 : 128 MB 알고리즘 분류 : 자료 구조, 이분 탐색, 트리를 사용한 집합과 맵
문제
N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.
입력
첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 \(-2^31\)보다 크거나 같고 \(2^31\)보다 작다.
출력
M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.
예제 입출력
Algorithm
1. bisect 사용 2. A List sort 3. bisect_left와 bisect_right의 값을 비교해 같으면 0, 다르면 1 출력
Code
import sys
from bisect import bisect_left, bisect_right
input = sys.stdin.readline
# 입력
N = int(input())
A = list(map(int, input().split()))
M = int(input())
B = list(map(int, input().split()))
# A 정렬
A.sort()
for i in B:
left = bisect_left(A, i)
right = bisect_right(A, i)
# left와 right의 값이 다르면 존재한다는 의미 -> 1 출력
if left != right:
print(1)
else: # 값이 같으면 존재하지 않는다는 의미 -> 0 출력
print(0)
Data의 중복(Data Redundancy) : File System은 각 File 마다 필요한 Data를 각각 가지고 있어야 하므로 동일한 Data를 서로 다른 File에 유지해 관리한다.
Data의 비일관성(Data Inconsistency) : 데이터에 변경사항이 조금만 있어도 각 File에서 해당되는 Data를 모두 변경해야 하므로 수정에 문제가 있고, 한꺼번에 수정이 되지 않으면 Data가 서로 달라진다.
정보 접근의 어려움(Difficulty in Accessing Data) : 기존 File System은 File의 용도에만 맞춰 제작되어 다른 Program을 만들 때는 기존의 Program을 변경하거나 개조하는 데 시간이 오래걸리며 다시 DataBase 작업을 해야한다.
Data의 고립(Data Isolation) : 정보가 여러 File에 서로 다른 형식으로 흩어져서 존재해 흩어진 정보를 이용하기 위해서는 재구성 비용이 들어가며 오랜 시간이 소요된다.
무결성 문제(Integrity Problems) : Data를 변경하기 위해서는 여러 File에 존재하는 Data에 모두 접근해 여러 번 변경해야 한다.
원자성 문제(Atomicity Problems) : Program이 수행 중인 작업은 전부 완료되어 저장되어하며 완료되지 못하면 아예 저장되지 않아야 한다. 즉, 수행중인 작업이 컴퓨터 고장이나 기타 의도하지 않은 이유로 중단되는 경우 작업을 전부 완료하지 못했으므로 저장하지 않고 이전의 Data를 복원한다.
동시 Access 문제 : 많은 사용자가 동시에 같은 정보에 접속해 갱신한다면 동시에 갱신되도록 해야한다. (= 정보의 일관성을 보장하도록 해야한다.)
2. DataBase
: 여러 사람이 공유하고 사용할 목적으로 통합 관리되는 Data들의 모임
2.1. 등장 목적
DataBase가 존재하기 전에는 File System을 사용해 Data를 관리했다. Data를 각각의 File 단위(Record)로 저장하며 이러한 일을 처리하기 위한 독립적인 Application과 상호 연동이 되어야 하는데 File System에서는 File에 접근하는 방식이 응용 프로그램 내에 표현되므로 응용 프로그램과 Data 간의 의존관계가 존재하게 되어 Data의 구조, 접근 방법이 변경되면 기존의 프로그램과 Data를 함께 변경해야한다.
즉, Data 정의가 응용 프로그램에 내포되어 있고 Program에서 Data를 접근하고 조작하는 것 외의 별도의 제어가 없다.
따라서, File 단위로 저장할 때 데이터 종속성 문제와 중복성, 데이터 무결성 문제 등이 존재해 DataBase로 관리하기 시작했다.
3. DBMS(DataBase Management System, 데이터베이스 관리 시스템)
: 다수의 사용자들이 DataBase 내의 Data의 생성, 접근 방법, 관리 유지할 수 있도록 전반적으로 지원하는 System
3.1. 기능
정의 기능 : DataBase를 관리하기 위해서는 저장할 구조를 정의해야하며 정의된 구조에 따라 저장해야한다.
조작 기능 : 사용자가 DataBase를 검색, 갱신, 삽입, 삭제 등을 할 수 있도록 지원하는 기능이다.
제어 기능 : DataBase의 정확성과 안정성을 위해 일정한 형식을 필터링해 저장하거나 여러 명이 Data를 동시 공유할 수 있도록 한다.
3.2. 특징
DBMS는 File System의 문제를 해결하기 위해 만들어졌기 때문에 DBMS의 특징은 곧 File System의 단점을 의미한다.
Data의 독립성
물리적 독립성 : DataBase의 Size를 늘리거나 성능 향상을 위해 Data File을 늘리거나 새롭게 추가하더라도 관련된 응용 프로그램을 수정할 필요가 없다.
논리적 독립성 : DataBase는 논리적인 구조로 다양한 응용 프로그램의 논리적 요구를 만족시킬 수 있다.
Data의 무결성 : 여러 경로를 통해 잘못된 Data가 발생하는 경우의 수를 방지하는 기능으로 Data의 유효성 검사를 통해 Data이 무결성을 구현한다.
Data의 보안성 : 인가된 사용자들만 DataBase나 DataBase 내의 자원에 접근할 수 있도록 계정 관리 및 접근 권한을 설정함으로써 모든 Data에 보안을 구현할 수 있다.
Data의 일관성 : 연관된 정보를 논리적인 구조로 관리함으로써 어떤 하나의 Data만 변경하는 경우 발생할 수 있는 Data의 불일치성을 배제할 수 있다. 또 작업 중 일부 Data만 변경되어 나머지 Data와 일치하지 않는 경우의 수를 배제할 수 있다.
Data 중복 최소화 : DataBase는 Data를 통합해서 관리함으로써 File System의 단점 중 하나인 자료의 중복과 Data의 중복 문제를 해결할 수 있다.
: 어떤 작업을 위해 실행할 수 있는 파일로 일반적으로 Application(End User가 사용할 수 있는 Software)이라고 많이 표현된다.
☞ Process를 이용해 실행시킨다.
2. 프로세스(Process)
: 컴퓨터에서 실행되고 있는 컴퓨터 프로그램으로 하나의 실행 단위가 된다.
☞ OS(Operating System)에서 실행 가능한 File을 Memory에 올리면 해당 File을 Process로 실행한다.
☞ 하나의 Application을 실행하면 최소 1개의 Process가 뜬다.
2.1. 구성 요소
Register : 명령이나 주소를 갖고 있는 CPU의 한 부분
Counter : Program 안에서 현재 어느 위치를 실행시키고 있는지 가리키는 용도로 사용
Stack : Function Call을 했을 때 Call Stack 등이 쌓이는 곳으로 지역 변수, 매개 변수, 반환값 등 일시적인 Data가 저장됨
Heap : Process가 가지고 있는 Memory 중 위쪽에 할당되어 있는 부분으로 동적으로 할당 가능한 Memory ☞ Memory Size에 제한이 없다.
Data : Static 변수, Global 변수 저장
Code : 실행 명령들을 포함하는 Code
2.2. 특징
각각 독립된 메모리 영역(Code, Data, Stack, Heap의 구조)을 할당받는다.
기본적으로 Process 당 최소 1개의 Thread를 가지고 있다.
각 Process는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료 구조에 접근할 수 없다.
한 Process가 다른 Process의 자원에 접근하려면 프로세스 간의 통신(IPC, Inter Process Communication)을 사용해야 한다. e.g., 파이프, 파일, 소켓 등을 이용한 통신 방법 이용
3. 스레드(Thread)
: Process 내에서 실행되는 여러 흐름의 단위
☞ Process는 여러 개의 Thread를 가질 수 있으며 Thread 간 자원을 공유하면서 동시에(Concurrency) 수행된다.
동시성(Concurrency) vs 병렬(Parallelism)
- 동시성(Concurrency) : 보이기에는 동시에 수행되는 것처럼 보이지만 실제로는 시간을 매우 잘게 쪼개서 CPU의 자원을 나눠서 쓰는 것 (진정한 의미의 병렬은 아님) Multi-Threading은 Concurrency에 가깝다.
- 병렬(Parallelism) : 실제로 동시에 수행되는 것 Multi-Processing은 Parallelism에 가깝다.
3.1. 특징
Thread는 Process 내에서 각각 Stack 영역만 따로 할당받고 Code, Data, Heap 영역은 공유한다.
한 Thread가 Process 자원을 변경하면, 다른 이웃 스레드(Sibling Thread)도 그 변경 결과를 즉시 볼 수 있다.
4. Thread vs Process
Process
Thread
의미
실행중인 Program
Process의 실행 단위
프로세스 종료 시간
오래 걸림
덜 걸림
생성 시간
오리 걸림
덜 걸림
Context Switching 소요 시간
오래 걸림
덜 걸림
Communication 측면에서의 효율성
떨어짐
효율적
자원 소비
더 많은 자원 소비
적은 자원 소비
메모리 공유
X
O
무게에 따른 이름
Heavy-weight Process
Light-Weight Process
전환 방식
OS의 Interface 사용
OS를 호출해 전환시킬 필요 없음
5. 멀티 태스킹(Multi Tasking)
: 한번에 여러 개의 Application을 실행시키는 것
☞ Multi-Processing과 Multi-Threading 기술이 가능해졌다고 설명할 수 있다.
Multi-Processing과 Multi-Threading
CPU의 최대 활용을 위해 프로그램의 둘 이상의 부분을 동시에 실행하는 기술 e.g., 하나의 Program 안에서 2개의 부분 동시 실행, 2개의 Program 동시 실행 등
5. 멀티 프로세스 (Multi Process)
: 하나의 응용프로그램을 여러 개의 프로세스로 구성해 각 프로세스가 하나의 작업(Task)을 처리하도록 하는 것
☞ Single Core에서 Multi Process 불가능
5.1. 장점 vs 단점
장점
단점
여러 개의 자식 Process 중 하나에 문제가 발생하면 그 자식 Process만 죽는 것 이상으로 다른 영향이 확산되지 않음
Context Switching에서의 Overhead : Context Switching 과정에서 Cache Memory 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등의 Overhead가 발생한다. Process는 각각의 독립된 Memory 영역을 할당받아 Process 사이에서 공유하는 Memory가 없으므로 Context Switching이 발생하면 Cache에 있는 모든 데이터 모두 리셋하고 다시 캐시 정보 불러와야 한다.
Process 사이의 어렵고 복잡한 통신 기법(IPC) : Process는 각각 독립된 Memory 영역을 할당받아 하나의 Program에 속하는 Process들 사이의 변수를 공유할 수 없다.
Context Switching (컨텍스트 전환, 작업 전환, 프로세스 전환) : 기본적으로 CPU의 자원을 Process/Thread에서 다른 Process/Thread로 전환하는 것으로 Context 전환을 통해 여러 Process가 단일 CPU를 공유할 수 있다. e.g., Process ↔ Process, Thread ↔ Thread, Process ↔ Thread ☞ Multi Tasking 운영체제의 주요 기능이다.
티어 : Silver 4 시간 제한 : 0.5 초 (추가 시간 없음) 메모리 제한 : 256 MB 알고리즘 분류 : 자료 구조, 스택
문제
정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.
명령은 총 다섯 가지이다.
push X: 정수 X를 스택에 넣는 연산이다. pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다. size: 스택에 들어있는 정수의 개수를 출력한다. empty: 스택이 비어있으면 1, 아니면 0을 출력한다. top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.
입력
첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.
티어 : Silver 5 시간 제한 : 0.5 초 (추가 시간 없음) 메모리 제한 : 128 MB 알고리즘 분류 : 수학, 다이나믹 프로그래밍, 조합론
문제
재원이는 한 도시의 시장이 되었다. 이 도시에는 도시를 동쪽과 서쪽으로 나누는 큰 일직선 모양의 강이 흐르고 있다. 하지만 재원이는 다리가 없어서 시민들이 강을 건너는데 큰 불편을 겪고 있음을 알고 다리를 짓기로 결심하였다. 강 주변에서 다리를 짓기에 적합한 곳을 사이트라고 한다. 재원이는 강 주변을 면밀히 조사해 본 결과 강의 서쪽에는 N개의 사이트가 있고 동쪽에는 M개의 사이트가 있다는 것을 알았다. (N ≤ M)
재원이는 서쪽의 사이트와 동쪽의 사이트를 다리로 연결하려고 한다. (이때 한 사이트에는 최대 한 개의 다리만 연결될 수 있다.) 재원이는 다리를 최대한 많이 지으려고 하기 때문에 서쪽의 사이트 개수만큼 (N개) 다리를 지으려고 한다. 다리끼리는 서로 겹쳐질 수 없다고 할 때 다리를 지을 수 있는 경우의 수를 구하는 프로그램을 작성하라.
입력
입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트케이스에 대해 강의 서쪽과 동쪽에 있는 사이트의 개수 정수 N, M (0 < N ≤ M < 30)이 주어진다.
출력
각 테스트 케이스에 대해 주어진 조건하에 다리를 지을 수 있는 경우의 수를 출력한다.
예제 입출력
Algorithm
1. nCk 조합 계산 : n! // (k! * (n-k)!) ☞ M 개 중에 N개를 골라서 다리를 놔야하기 때문
Code
def factorial(num):
if num < 2:
return 1
else:
return num * factorial(num-1)
T = int(input())
for _ in range(T):
N, M = map(int, input().split())
print(factorial(M) // (factorial(N) * factorial(M - N)))