728x90

문제

요세푸스 문제는 다음과 같다.

1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.

N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)

출력

예제와 같이 요세푸스 순열을 출력한다.

코드

import sys
n,k = map(int,sys.stdin.readline().split())
q=[]
result = []
for i in range(1,n+1):
    q.append(i)

index = 0
while q:
    index += k-1
    if index >= len(q):
        index = index % len(q)

    result.append(q.pop(index))

print("<", ', '.join(str(i) for i in result),">",sep="")

풀이

index 는 삭제할 인덱스이고 계속 k만큼 더해주는데 배열의 인덱스이니까 k-1을 더해준다.

삭제할 인덱스가 큐 한바퀴를 돌면, 원 모양이니까 다시 인덱스가 돌아가야한다.

index = index % len(q)

이렇게 하면 돌아갈 수 있다.

 

마지막 출력은 join()함수를 써서 깔끔하게 작성한다.

', '.join(i for i in result)로 하면 result에 있는 i는 정수여서 str로 바꿔서 join해야한다.

이 때, "<", ">"를 쉼표로 같이 이어붙이면 공백이 발생한다.

정답은 공백을 제거해야하니까 sep = ""로 제거해준다.

 

728x90

문제

스택 (stack)은 기본적인 자료구조 중 하나로, 컴퓨터 프로그램을 작성할 때 자주 이용되는 개념이다. 스택은 자료를 넣는 (push) 입구와 자료를 뽑는 (pop) 입구가 같아 제일 나중에 들어간 자료가 제일 먼저 나오는 (LIFO, Last in First out) 특성을 가지고 있다.

1부터 n까지의 수를 스택에 넣었다가 뽑아 늘어놓음으로써, 하나의 수열을 만들 수 있다. 이때, 스택에 push하는 순서는 반드시 오름차순을 지키도록 한다고 하자. 임의의 수열이 주어졌을 때 스택을 이용해 그 수열을 만들 수 있는지 없는지, 있다면 어떤 순서로 push와 pop 연산을 수행해야 하는지를 알아낼 수 있다. 이를 계산하는 프로그램을 작성하라.

입력

첫 줄에 n (1 ≤ n ≤ 100,000)이 주어진다. 둘째 줄부터 n개의 줄에는 수열을 이루는 1이상 n이하의 정수가 하나씩 순서대로 주어진다. 물론 같은 정수가 두 번 나오는 일은 없다.

출력

입력된 수열을 만들기 위해 필요한 연산을 한 줄에 한 개씩 출력한다. push연산은 +로, pop 연산은 -로 표현하도록 한다. 불가능한 경우 NO를 출력한다.

코드

import sys
n = int(sys.stdin.readline())
stack = []
op = []
now = 1
possible = 1
for i in range(n):
    num = int(sys.stdin.readline())
    while now <= num:
        stack.append(now)
        op.append('+')
        now+=1

    if stack[-1] == num:
        stack.pop()
        op.append('-')
    else:
        possible = 0
if possible ==0:
    print("NO")
else:
    for i in op:
        print(i)

풀이

push()를 1부터 n까지 오름차순으로 해야한다.

그럼 입력값이 pop() 이 가능할 때까지 1부터 스택에 append() 해준다.

입력값이 pop()가능하면 pop()하고

불가능하면 NO 출력한다.

728x90

문제

두 개의 자연수를 입력받아 최대 공약수와 최소 공배수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에는 두 개의 자연수가 주어진다. 이 둘은 10,000이하의 자연수이며 사이에 한 칸의 공백이 주어진다.

출력

첫째 줄에는 입력으로 주어진 두 수의 최대공약수를, 둘째 줄에는 입력으로 주어진 두 수의 최소 공배수를 출력한다.

코드1

import math
import sys
a,b = map(int,sys.stdin.readline().split())
print(math.gcd(a,b))
print(math.lcm(a,b))

풀이

python의 math라이브러리는

최대공약수 math.gcd(a,b)

최소공배수 math.lcm(a,b)를 제공한다.

코드2

import math
import sys
a,b = map(int,sys.stdin.readline().split())

def GCD(a,b):
    while b>0:
        a,b = b, a%b
    return a
    
def LCM(a,b):
    return int(a*b / GCD(a,b))
    
print(GCD(a,b))
print(LCM(a,b))

풀이

유클리드 호제법

최대공약수

a,b의 최대공약수는 a를 b로 나눈 나머지와 b의 최대공약수와 같다.

 

최소공배수는

a,b를 곱한 값을 a,b의 최대공약수로 나눈 값이 최소공배수이다.

 

외워잉

728x90

문제

M이상 N이하의 소수를 모두 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.

출력

한 줄에 하나씩, 증가하는 순서대로 소수를 출력한다.

코드

import sys
import math
n, m = map(int,sys.stdin.readline().split())
arr = [True for i in range(m+1)]
for i in range(2,int(math.sqrt(m))+1):
    if arr[i]==True:
        j=2
        while i*j <= m:
            arr[i*j] = False
            j+=1
for i in range(n,m+1):
    if i>1 and arr[i]:
        print(i)

풀이

데이터가 1,000,000 개 이하에서 여러 소수를 구하는 문제는 에라토스테네스의 체 알고리즘을 사용한다.

 

구해야하는 크기만큼의 True 배열을 만든다.

2부터 구해야하는 크기의 제곱근까지의 자기자신을 제외한 배수를 모두 False을 만든다.

2부터 2를 제외하고 4, 6, 8, 10... False

3부터 3을 제외하고 3, 6, 9, 12 ... False

...

이렇게 하고 True 인 것만 출력하면 소수만 나온다.

 

마지막에 출력 시, i는 2부터임을 주의하자.

 

728x90

문제

한 줄로 된 간단한 에디터를 구현하려고 한다. 이 편집기는 영어 소문자만을 기록할 수 있는 편집기로, 최대 600,000글자까지 입력할 수 있다.

이 편집기에는 '커서'라는 것이 있는데, 커서는 문장의 맨 앞(첫 번째 문자의 왼쪽), 문장의 맨 뒤(마지막 문자의 오른쪽), 또는 문장 중간 임의의 곳(모든 연속된 두 문자 사이)에 위치할 수 있다. 즉 길이가 L인 문자열이 현재 편집기에 입력되어 있으면, 커서가 위치할 수 있는 곳은 L+1가지 경우가 있다.

이 편집기가 지원하는 명령어는 다음과 같다.

LDBP $
커서를 왼쪽으로 한 칸 옮김 (커서가 문장의 맨 앞이면 무시됨)
커서를 오른쪽으로 한 칸 옮김 (커서가 문장의 맨 뒤이면 무시됨)
커서 왼쪽에 있는 문자를 삭제함 (커서가 문장의 맨 앞이면 무시됨)
삭제로 인해 커서는 한 칸 왼쪽으로 이동한 것처럼 나타나지만, 실제로 커서의 오른쪽에 있던 문자는 그대로임
$라는 문자를 커서 왼쪽에 추가함

초기에 편집기에 입력되어 있는 문자열이 주어지고, 그 이후 입력한 명령어가 차례로 주어졌을 때, 모든 명령어를 수행하고 난 후 편집기에 입력되어 있는 문자열을 구하는 프로그램을 작성하시오. 단, 명령어가 수행되기 전에 커서는 문장의 맨 뒤에 위치하고 있다고 한다.

입력

첫째 줄에는 초기에 편집기에 입력되어 있는 문자열이 주어진다. 이 문자열은 길이가 N이고, 영어 소문자로만 이루어져 있으며, 길이는 100,000을 넘지 않는다. 둘째 줄에는 입력할 명령어의 개수를 나타내는 정수 M(1 ≤ M ≤ 500,000)이 주어진다. 셋째 줄부터 M개의 줄에 걸쳐 입력할 명령어가 순서대로 주어진다. 명령어는 위의 네 가지 중 하나의 형태로만 주어진다.

출력

첫째 줄에 모든 명령어를 수행하고 난 후 편집기에 입력되어 있는 문자열을 출력한다.

코드

import sys
s = list(sys.stdin.readline().rstrip())
n = int(sys.stdin.readline())
cursor = len(s)
for i in range(n):
    orders = sys.stdin.readline().split()
    if orders[0] == "L":
        if cursor == 0:
            continue
        cursor -= 1
    elif orders[0] == "D":
        if cursor == len(s):
            continue
        cursor += 1
    elif orders[0] == "B":
        if cursor == 0:
            continue
        s.remove(s[cursor-1])
        cursor-=1
    elif orders[0] == "P":
        s.insert(cursor,orders[1])
        cursor+=1
print(''.join(s))

풀이

시간초과나서 다른 사람 풀이를 참고했다....

WOW 

나는 슈퍼 멍충이...공부하자

 

stack을 2개 사용했다.

커서 기준으로 커서 왼쪽 관련이면 입력받은 s1에서 해결, 오른쪽 관련이면 s2에서 해결한다.

 

  1. L이면 s1에 맨 위에 있는 것을 s2에 삽입
  2. D이면 s2에 맨 위에 있는 것을 s1에 삽입
  3. B이면 s1에 맨 위에 삭제
  4. P이면 s1에 입력 원소 삽입

 

이렇게 조건에 만족하면 s1+s2을 출력 시에 s2는 뒤집어서 출력해야한다.

list(reversed(s2)

다른 사람 코드

import sys
s1 = list(sys.stdin.readline().rstrip())
n = int(sys.stdin.readline())
s2 = []
for i in range(n):
    orders = sys.stdin.readline().split()
    if orders[0] == "L" and len(s1)!=0:
        s2.append(s1.pop())
    elif orders[0] == "D" and len(s2)!=0:
        s1.append(s2.pop())
    elif orders[0] == "B" and len(s1)!=0:
        s1.pop()
    elif orders[0] == "P":
        s1.append(orders[1])
print(''.join(s1+list(reversed(s2))))
728x90

문제

정수를 저장하는 덱(Deque)를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여덟 가지이다.

  • push_front X: 정수 X를 덱의 앞에 넣는다.
  • push_back X: 정수 X를 덱의 뒤에 넣는다.
  • pop_front: 덱의 가장 앞에 있는 수를 빼고, 그 수를 출력한다. 만약, 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • pop_back: 덱의 가장 뒤에 있는 수를 빼고, 그 수를 출력한다. 만약, 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 덱에 들어있는 정수의 개수를 출력한다.
  • empty: 덱이 비어있으면 1을, 아니면 0을 출력한다.
  • front: 덱의 가장 앞에 있는 정수를 출력한다. 만약 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • back: 덱의 가장 뒤에 있는 정수를 출력한다. 만약 덱에 들어있는 정수가 없는 경우에는 -1을 출력한다.

입력

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.

출력

출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.

코드

import sys
from collections import deque
input = sys.stdin.readline
n = int(input())
q = deque()
for i in range(n):
    orders = input().split()

    if orders[0] == 'push_front':
        q.appendleft(orders[1])
    elif orders[0] == 'push_back':
        q.append(orders[1])
    elif orders[0] == 'pop_front':
        if len(q) == 0:
            print(-1)
        else:
            print(q.popleft())
    elif orders[0] == 'pop_back':
        if len(q) == 0:
            print(-1)
        else:
            print(q.pop())
    elif orders[0] == 'size':
        print(len(q))
    elif orders[0] == 'empty':
        if len(q) == 0:
            print(1)
        else:
            print(0)
    elif orders[0] == 'front':
        if len(q) == 0:
            print(-1)
        else:
            print(q[0])
    elif orders[0] == 'back':
        if len(q) == 0:
            print(-1)
        else:
            print(q[-1])

풀이

collections 의 deque를 사용했다.

deque는 첫 번째 원소를 제거할 때 popleft(), 마지막 원소를 제거할 때 pop()

첫 번째 인덱스에 원소 a 추가 할때 appendleft(a) , 마지막 인덱스에 원소를 삽입할 때 append(a)

728x90

문제

정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여섯 가지이다.

  • push X: 정수 X를 큐에 넣는 연산이다.
  • pop: 큐에서 가장 앞에 있는 정수를 빼고, 그 수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 큐에 들어있는 정수의 개수를 출력한다.
  • empty: 큐가 비어있으면 1, 아니면 0을 출력한다.
  • front: 큐의 가장 앞에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • back: 큐의 가장 뒤에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.

입력

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.

출력

출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.

코드

import sys
from collections import deque
n = int(input())
q = deque()
for i in range(n):
    orders = sys.stdin.readline().split()

    if orders[0] == 'push':
        q.append(orders[1])
    elif orders[0] == 'pop':
        if len(q) == 0:
            print(-1)
        else:
            print(q.popleft())
    elif orders[0] == 'size':
        print(len(q))
    elif orders[0] == 'empty':
        if len(q) == 0:
            print(1)
        else:
            print(0)
    elif orders[0] == 'front':
        if len(q) == 0:
            print(-1)
        else:
            print(q[0])
    elif orders[0] == 'back':
        if len(q) == 0:
            print(-1)
        else:
            print(q[-1])

풀이

sys 라이브러리로 입력받고 명령대로 수행한다.

python에서 큐는 리스트로도 가능하지만 collections에서 deque를 사용했다.

'알고리즘 문제 풀이 > 백준' 카테고리의 다른 글

[백준] 1406 에디터 python (*)  (0) 2022.02.18
[백준] 10866 덱 python  (0) 2022.02.17
[백준] 10828 스택 python  (0) 2022.02.16
[백준] 10814 나이순 정렬 python  (0) 2022.02.15
[백준] 2529 부등호 python (*)  (0) 2022.02.15

+ Recent posts